I am wondering if HttpWebRequest can be used to fill a MVC model? I am trying to build a MVC 4 application where I take data from a college course listing page and massage it in a few different ways in my View. The examples that I have been seeing around have all taken a response stream and returned a string or have not been formatted for MVC (using console.write). Also, as far as I understand, the data as its being returned isn't in a JSON or XML format. Here is my controller so far...
public ActionResult Index()
{
string postData = "semester=20143Fall+2013+++++++++++++++++++++++++++++++&courseid=&subject=IT++INFORMATION+TECHNOLOGY&college=&campus=1%2C2%2C3%2C4%2C5%2C6%2C7%2C9%2CA%2CB%2CC%2CI%2CL%2CM%2CN%2CP%2CQ%2CR%2CS%2CT%2CW%2CU%2CV%2CX%2CZ&courselevel=&coursenum=&startTime=0600&endTime=2359&days=ALL&All=All+Sections";
byte[] dataArray = Encoding.UTF8.GetBytes (postData);
HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create("http://www3.mnsu.edu/courses/selectform.asp");
myRequest.Method = "POST";
myRequest.ContentType = "application/x-www-form-urlencoded";
myRequest.ContentLength = dataArray.Length;
using (WebResponse response = myRequest.GetResponse())
{
using (var reader = new StreamReader(response.GetResponseStream()))
{
//insert into a model? Maybe?
}
}
return View();
}
If HttbWebRequest can't be used, is there a way that would work? Or am I completely heading in the wrong direction?
You can using HttpWebRequest and WebResponse to get stream from your college course's web site. Then use HtmlAgilityPack to parse scrap in the stream and insert your desired value into model
Related
I originally asked a question regarding a WCF web service that I was trying to write and then found that the ASP.net web API was more appropriate to my needs, due to some feedback on here.
I've now found a good tutorial that tells me how to create a simple REST service using Web API which works well pretty much out of the box.
My question
I have a POST method in my REST service server:
// POST api/values/5
public string Post([FromBody]string value)
{
return "Putting value: " + value;
}
I can POST to this using POSTER and also my C# client code.
However the bit I don't understand is why I have to prepend an '=' sign to the POST data so that it reads: "=Here is my data which is actually a JSON string"; rather than just sending: "Here is my data which is actually a JSON string";
My C# Client that talks to the REST service is written as follows:
public string SendPOSTRequest(string sFunction, string sData)
{
string sResponse = string.Empty;
// Create the request string using the data provided
Uri uriRequest = GetFormRequest(m_sWebServiceURL, sFunction, string.Empty);
// Data to post
string sPostData = "=" + sData;
// The Http Request obj
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uriRequest);
request.Method = m_VERB_POST;
System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
Byte[] byteArray = encoding.GetBytes(sPostData);
request.ContentLength = byteArray.Length;
request.ContentType = m_APPLICATION_FORM_URLENCODED;
try
{
using (Stream dataStream = request.GetRequestStream())
{
dataStream.Write(byteArray, 0, byteArray.Length);
}
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (Stream stream = response.GetResponseStream())
{
StreamReader reader = new StreamReader(stream, Encoding.UTF8);
sResponse = reader.ReadToEnd();
}
}
}
catch (WebException ex)
{
//Log exception
}
return sResponse;
}
private static Uri GetFormRequest(string sURL, string sFunction, string sParam)
{
StringBuilder sbRequest = new StringBuilder();
sbRequest.Append(sURL);
if ((!sURL.EndsWith("/") &&
(!string.IsNullOrEmpty(sFunction))))
{
sbRequest.Append("/");
}
sbRequest.Append(sFunction);
if ((!sFunction.EndsWith("/") &&
(!string.IsNullOrEmpty(sParam))))
{
sbRequest.Append("/");
}
sbRequest.Append(sParam);
return new Uri(sbRequest.ToString());
}
Is anybody able to explain why I have to prepend the '=' sign as in the above code (string sPostData = "=" + sData;)?
Many thanks in advance!
The content type x-www-form-urlencoded is a key-value format. With form bodies you are only able to read a single simple type from a request body. As a name is expected, but in this case not allowed, you have to prefix the equal sign to indicate that there is no name with the followed value.
However, you should lean away from accepting simple types within the body of your web-api controller actions.
You are limited to only a single simple type if you attempt to pass data in the body of an HttpPost/HttpPut without directly implementing your own MediaTypeFormatter, which is unlikely to be reliable. Creating a light-weight complex type is generally much more preferable, and will make interoperating with other content-types, like application/json, much easier.
I've set up a page to do an HTTP Post with a Json serialized generic list, to a different page in ASP.net. When it goes to the new page though, I can't seem to find the body of the HTTP Post.
This is the method for the post:
public static void SendHttpPost(string json)
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create("http://localhost:57102/Post.aspx");
httpWebRequest.ContentType = "text/json";
httpWebRequest.Method = "POST";
using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
}
}
}
Although this is the first time I've done this, I presumed you would be able to access the Json using Request.Form or similar, but Request.Form is empty. I've had a good look at the VS degugger and can't see it anywhere in the Request object, but the content length is 68000 bytes, so I'm sure it's in there somewhere!
Can anyone point me in the right direction please? Many thanks
You can retrieve the Request Body using Request.InputStream as shown here : gist.github.com/leggetter/769688 !
I have the following MVC method.
[System.Web.Mvc.HttpPost]
public ActionResult Listen(string status)
{
CFStatusMessage statusMessage = new CFStatusMessage();
if (!string.IsNullOrEmpty(status))
{
statusMessage = Newtonsoft.Json.JsonConvert.DeserializeObject<CFStatusMessage>(status);
}
return Content(Server.HtmlEncode(status));// View(statusMessage);
}
I am trying to call the above method from Other application .. (Console). I am using HttpWebRequest to make a call to the MVC Method. Using the below code its able to call the method but the Parameter is always coming as empty string.
string content = "{\"status\":\"success\",\"payload\":\"some information\"}";
string url = "http://myrl.com";
var httpWRequest = (HttpWebRequest) WebRequest.Create(url);
httpWRequest.Method = "POST";
httpWRequest.ContentType = "text/json";
var encoding = new ASCIIEncoding();
byte[] data = encoding.GetBytes(string.Format("status={0}", Uri.EscapeDataString(content)));
httpWRequest.ContentLength = data.Length;
Stream stream = httpWRequest.GetRequestStream();
stream.Write(data, 0, data.Length);
var response = (HttpWebResponse)httpWRequest.GetResponse();
With this its making a call to Listen method but status parameter is always coming blank. whereas I want the json string {status:"success",payload:"some information"} as parameter.
What am I doing wrong?
P.S.: I tried the below statement as well, while sending the actual content.
byte[] data = encoding.GetBytes(content);
Regards,
M
If do you need to provide any kind of service from MVC tryout WebApi instead. You can use HTTP REST to do this easily.
Read more here ASP.NET WebApi
You appear to be saying the request is json, but sending it using wwwencoding.
Remove the status={0} line bit & just send the json as is.
You can try something like this
using (var sw = new StreamWriter(httpWRequest.GetRequestStream()))
{
sw.Write(content);
sw.Flush();
sw.Close();
}
I am hosting a web service in ASP.Net MVC3 which returns a Json string. What is the best way to call the webservice from a c# console application, and parse the return into a .NET object?
Should I reference MVC3 in my console app?
Json.Net has some nice methods for serializing and deserializing .NET objects, but I don't see that it has ways for POSTing and GETing values from a webservice.
Or should I just create my own helper method for POSTing and GETing to the web service? How would I serialize my .net object to key value pairs?
I use HttpWebRequest to GET from the web service, which returns me a JSON string. It looks something like this for a GET:
// Returns JSON string
string GET(string url)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
try {
WebResponse response = request.GetResponse();
using (Stream responseStream = response.GetResponseStream()) {
StreamReader reader = new StreamReader(responseStream, System.Text.Encoding.UTF8);
return reader.ReadToEnd();
}
}
catch (WebException ex) {
WebResponse errorResponse = ex.Response;
using (Stream responseStream = errorResponse.GetResponseStream())
{
StreamReader reader = new StreamReader(responseStream, System.Text.Encoding.GetEncoding("utf-8"));
String errorText = reader.ReadToEnd();
// log errorText
}
throw;
}
}
I then use JSON.Net to dynamically parse the string.
Alternatively, you can generate the C# class statically from sample JSON output using this codeplex tool: http://jsonclassgenerator.codeplex.com/
POST looks like this:
// POST a JSON string
void POST(string url, string jsonContent)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
Byte[] byteArray = encoding.GetBytes(jsonContent);
request.ContentLength = byteArray.Length;
request.ContentType = #"application/json";
using (Stream dataStream = request.GetRequestStream()) {
dataStream.Write(byteArray, 0, byteArray.Length);
}
long length = 0;
try {
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) {
length = response.ContentLength;
}
}
catch (WebException ex) {
// Log exception and throw as for GET example above
}
}
I use code like this in automated tests of our web service.
WebClient to fetch the contents from the remote url and JavaScriptSerializer or Json.NET to deserialize the JSON into a .NET object. For example you define a model class which will reflect the JSON structure and then:
using (var client = new WebClient())
{
var json = client.DownloadString("http://example.com/json");
var serializer = new JavaScriptSerializer();
SomeModel model = serializer.Deserialize<SomeModel>(json);
// TODO: do something with the model
}
There are also some REST client frameworks you may checkout such as RestSharp.
Although the existing answers are valid approaches , they are antiquated . HttpClient is a modern interface for working with RESTful web services . Check the examples section of the page in the link , it has a very straightforward use case for an asynchronous HTTP GET .
using (var client = new System.Net.Http.HttpClient())
{
return await client.GetStringAsync("https://reqres.in/api/users/3"); //uri
}
I have a page that collects data and 'POST's to another site. I could just put he site url in the action of the form tag but I would like to record the information in my database prior to switching sites. In the ActionResult so far I have:
[HttpPost]
public ActionResult MyPage(MyPageModel model)
{
if (ModelState.IsValid)
{
StoreDate(model.fld1, model.fld2)
var encoding = new ASCIIEncoding();
var postData = "";
foreach (String postKey in Request.Form)
{
var postValue = Encode(Request.Form[postKey]);
postData += string.Format("&{0}={1}", postKey, postValue);
}
var data = encoding.GetBytes(postData);
// Prepare web request...
var myRequest = (HttpWebRequest)WebRequest.Create("https://www.site2.com");
myRequest.Method = "POST";
myRequest.ContentType = "application/x-www-form-urlencoded";
myRequest.ContentLength = data.Length;
// Send the data.
Stream newStream = myRequest.GetRequestStream();
newStream.Write(data, 0, data.Length);
newStream.Flush();
newStream.Close();
Does anyone know how to finish this and use the proper 'return' varient to have this post the data to the other site.
I have edited the snippet based on a response below.
The POST has already happened, so there's not going to be a magic bullet (i.e. a simple ActionResult) that will work for you. Since you're handling the POST response on your server, you'll need to recreate the POST request to the target server yourself. To do that you'll need to leverage an HttpWebRequest vis a vis this answer. After getting the response back from the HttpWebRequest, you'll need to pass that response back, probably via a ContentResult. All in all, it will be non-trivial, but it is possible.
Update:
Based on your snippet, I'd try adding the following:
WebResponse res = myRequest.GetResponse();
StreamReader sr = new StreamReader(res.GetResponseStream());
string returnvalue = sr.ReadToEnd();
return Content(returnValue);
Another option would be to point the form action at the other site and do an ajax post to your server before submitting the form. That would be much easier than playing man-in-the-middle with HttpWebRequest.