Why return 500 error while calling another controller using WebClient? - asp.net-mvc-4

I'm testing example on this link: http://msdn.microsoft.com/en-us/vs11trainingcourse_aspnetmvc4_topic5#_Toc319061802 but I have 500 error calling another controller using WebClient.
When I access to "http://localhost:2323/photo/gallery directly is running, but I'm trying from action using WebClient it return 500 error? Why?"
public ActionResult Index()
{
WebClient client = new WebClient();
var response = client.DownloadString(Url.Action("gallery", "photo", null, Request.Url.Scheme));
var jss = new JavaScriptSerializer();
var result = jss.Deserialize<List<Photo>>(response);
return View(result);
}
500 error created by below exception:
[ArgumentNullException: Value cannot be null.
Parameter name: input]
System.Text.RegularExpressions.Regex.Match(String input) +6411438
Microsoft.VisualStudio.Web.Runtime.Tracing.UserAgentUtilities.GetEurekaVersion(String userAgent) +79
Microsoft.VisualStudio.Web.Runtime.Tracing.UserAgentUtilities.IsRequestFromEureka(String userAgent) +36
Microsoft.VisualStudio.Web.Runtime.Tracing.SelectionMappingExecutionListenerModule.OnBeginRequest(Object sender, EventArgs e) +181
System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +136
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +69

It's hard to tell. Maybe the controller action that you are calling requires authorization? Or uses session? When you send your WebClient request it doesn't delegate any of the client cookies that were sent by the client to the Index action.
Here's how you can debug your code and see the exact response returned by the server:
WebClient client = new WebClient();
try
{
var response = client.DownloadString(Url.Action("gallery", "photo", null, Request.Url.Scheme));
}
catch (WebException ex)
{
using (var reader = new StreamReader(ex.Response.GetResponseStream()))
{
string responseText = reader.ReadToEnd(); // <-- Look here to get more details about the error
}
}
And if it turns out that the problem is related to the ASP.NET Session that your target controller action depends upon, here's how you could delegate the client cookies with the request:
WebClient client = new WebClient();
client.Headers[HttpRequestHeader.Cookie] = Request.Headers["Cookie"];

error occurred because of the User-Agent Header
Resolution is:
public ActionResult Index()
{
WebClient client = new WebClient();
client.Headers[HttpRequestHeader.UserAgent] = Request.Headers["User-Agent"];
var response = client.DownloadString(Url.Action("gallery", "photo", null, Request.Url.Scheme));
var jss = new JavaScriptSerializer();
var result = jss.Deserialize<List<Photo>>(response);
return View(result);
}

Related

Forward POST request from asp.net core controller to different URL

I wanto to forward an incoming POST request to my asp.net core controller "as is" (including headers, body, from-data) to a different URL without using a middleware.
I found an example for doing that for asp.net: https://philsversion.com/2012/09/06/creating-a-proxy-with-apicontroller/
But this does not work for asp.net core, since the call to
return await http.SendAsync(this.Request);
in asp.net core accepts an HttpRequestMessage and the Request object is of type HttpRequest.
I also found some code, which creates a HttpRequestMessage from an HttpRequest, see: Convert Microsoft.AspNetCore.Http.HttpRequest to HttpRequestMessage
Using this code, the receiving endpoint (to which I forward to) gets the Body, but it does not get Form fields.
Checking the class HttpRequestMessage I saw that it does not contain a property for FormFields.
[Microsoft.AspNetCore.Mvc.HttpPost]
[NrgsRoute("api/redirect-v1/{key}")]
public async Task<HttpResponseMessage> Forward(
[FromUri] string key,
CancellationToken cancellationToken)
{
// the URL was shortened, we need to get the original URL to which we want to forward the POST request
var url = await _shortenUrlService.GetUrlFromToken(key, cancellationToken).ConfigureAwait(false);
using (var httpClient = new HttpClient())
{
var forwardUrl = new Uri(url);
Request.Path = new PathString(forwardUrl.PathAndQuery);
// see: https://stackoverflow.com/questions/45759417/convert-microsoft-aspnetcore-http-httprequest-to-httprequestmessage
var requestMessage = Request.ToHttpRequestMessage();
return await httpClient.SendAsync(requestMessage, cancellationToken);
// Problem: Forwards header and body but NOT form fields
}
}
Expected result would be that at my receiving endpoint I have the same
- headers
- body
- form fields
as in the original POST request.
I ended up doing the following:
[HttpPost]
[NrgsRoute("api/redirect-v1/{key}")]
public async Task<RedirectResult> Forward(string key, CancellationToken cancellationToken)
{
var url = await _shortenUrlService.GetUrlFromToken(key, cancellationToken).ConfigureAwait(false);
if (string.IsNullOrEmpty(url))
throw new BadRequestException($"Could not create forward URL from parameter {key}", "redirect-error");
using (var httpClient = new HttpClient())
{
var forwardUrl = new Uri(url);
Request.Path = new PathString(forwardUrl.PathAndQuery);
HttpResponseMessage responseMessage;
if (Request.HasFormContentType)
responseMessage = await ForwardFormData(key, httpClient, forwardUrl, cancellationToken);
else
responseMessage = await ForwardBody(key, httpClient, cancellationToken);
var queryParams = forwardUrl.GetQueryStringParams();
var lUlr = queryParams["lurl"];
return new RedirectResult(lUlr);
}
}
private async Task<HttpResponseMessage> ForwardFormData(string key, HttpClient httpClient, Uri forwardUrl, CancellationToken cancellationToken)
{
var formContent = new List<KeyValuePair<string, string>>();
HttpResponseMessage result;
if (Request.ContentType == "application/x-www-form-urlencoded")
{
foreach (var formKey in Request.Form.Keys)
{
var content = Request.Form[formKey].FirstOrDefault();
if (content != null)
formContent.Add(new KeyValuePair<string, string>(formKey, content));
}
var formUrlEncodedContent = new FormUrlEncodedContent(formContent);
result = await httpClient.PostAsync(forwardUrl, formUrlEncodedContent, cancellationToken);
}
else
{
var multipartFormDataContent = new MultipartFormDataContent();
foreach (var formKey in Request.Form.Keys)
{
var content = Request.Form[formKey].FirstOrDefault();
if (content != null)
multipartFormDataContent.Add(new StringContent(content), formKey);
}
result = await httpClient.PostAsync(forwardUrl, multipartFormDataContent, cancellationToken);
}
return result;
}
private async Task<HttpResponseMessage> ForwardBody(string key, HttpClient httpClient, CancellationToken cancellationToken)
{
// we do not have direct access to Content, see: https://stackoverflow.com/questions/41508664/net-core-forward-a-local-api-form-data-post-request-to-remote-api
var requestMessage = Request.ToHttpRequestMessage();
return await httpClient.SendAsync(requestMessage, cancellationToken);
}

How to receive a response package from GET request for OneNote API

I'm getting a acknowledgement but no response message (details) i.e. list of notebooks from the OneNote API. Below is my code. I am able to receive the header and JSON details from a POST message but not the GET. I have tried to convert the POST code in order to submit a GET request.
private async void getRequestClick(object sender, RoutedEventArgs e)
{
await GetRequests(true, "test");
}
async public Task<StandardResponse> GetRequests(bool debug, string sectionName)
{
Uri PagesEndPoint1 = new Uri("https://www.onenote.com/api/v1.0/notebooks");
var client = new HttpClient();
//// Note: API only supports JSON return type.
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
//// This allows you to see what happens when an unauthenticated call is made.
if (IsAuthenticated)
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authClient.Session.AccessToken);
}
HttpResponseMessage response;
HttpRequestMessage createMessage = new HttpRequestMessage(HttpMethod.Get, PagesEndPoint1);
response = await client.SendAsync(createMessage);
tbResponse.Text = response.ToString();
return await TranslateResponse(response);
}
private async static Task<StandardResponse> TranslateResponse(HttpResponseMessage response)
{
StandardResponse standardResponse;
if (response.StatusCode == HttpStatusCode.Created)
{
dynamic responseObject = JsonConvert.DeserializeObject(await response.Content.ReadAsStringAsync());
standardResponse = new CreateSuccessResponse
{
StatusCode = response.StatusCode,
OneNoteClientUrl = responseObject.links.oneNoteClientUrl.href,
OneNoteWebUrl = responseObject.links.oneNoteWebUrl.href
};
}
else
{
standardResponse = new StandardErrorResponse
{
StatusCode = response.StatusCode,
Message = await response.Content.ReadAsStringAsync()
};
}
// Extract the correlation id. Apps should log this if they want to collcet the data to diagnose failures with Microsoft support
IEnumerable<string> correlationValues;
if (response.Headers.TryGetValues("X-CorrelationId", out correlationValues))
{
standardResponse.CorrelationId = correlationValues.FirstOrDefault();
}
return standardResponse;
}
My POST messages are working OK. I can create a new page etc.
I think you need to change the expected status code from HttpStatusCode.Created to HttpStatusCode.OK for Get requests, since they return a 200 and not a 201. Try doing that in your TranslateResponse method.

httpwebrequest is not waiting for my response

I have a JavaScriptHelper class with a custom WebPost method as follows:
public string WebPost(string url, string json)
{
#region
string responseData = "";
try
{
HttpWebRequest webRequest = System.Net.WebRequest.Create(url) as HttpWebRequest;
StreamWriter requestWriter = null;
webRequest.Method = "POST";
webRequest.ContentType = "application/json";
using (requestWriter = new StreamWriter(webRequest.GetRequestStream()))
{
requestWriter.Write(json);
}
using (StreamReader responseReader = new StreamReader(webRequest.GetResponse().GetResponseStream()))
{
responseData = responseReader.ReadToEnd();
}
webRequest = null;
}
catch (WebException ex)
{
LogBase.LogController.WriteError(ex);
}
catch (Exception ex)
{
LogBase.LogController.WriteError(ex);
}
return responseData;
#endregion
}
I use this to send a POST request to an ASP.NET WebAPI service as follows:
RegisterModel model = new RegisterModel();
model.email = "abc#gmail.com";
model.oAuthId = "11111111";
model.oAuthType = "Facebook";
string jsonStr = JsonConvert.SerializeObject(model);
string response = new JavaScriptHelper().WebPost("http://localhost:9091/api/Authentication/authenticateoauth", jsonStr);
The service receives this call. If the user exists, it returns the response, if it doesnt, it creates the user and returns the response.
The problem I am facing is that when the user exists, everything works fine. I get the response on the client (JSON). When it doesn't exists, it creates the user correctly on the server, but my client breaks off early and doesn't wait for a response. I get the following error:
System.Net.WebException was unhandled
HResult=-2146233079
Message=The remote server returned an error: (500) Internal Server Error.
Source=System
StackTrace:
at System.Net.HttpWebRequest.GetResponse()
How can I force my request to wait for a response a little longer?

Error on WP7 app WebRequest

I have this errors on 'error List'.
'ContentLength' is not a member of 'System.Net.WebRequest'
'GetRequestStream' is not a member of 'System.Net.WebRequest'
'GetResponse' is not a member of 'System.Net.WebRequest'
I'm make an App WindowsPhone 7 with vb.net on VisualStudio 2010
i can't understand why. Thanks
You can't due to the async nature of WP. It seems like you have lifted examples from a non WP project. In WP, you have to make the call and then register an even that listens to the completion of the task. Further reading on Async Calls
private void GetSource(object sender, RoutedEventArgs e)
{
System.Net.WebRequest request = WebRequest.Create("http://www.bbc.co.uk");
//request.ContentType = "application/json";
request.Method = "GET";
request.BeginGetResponse(new AsyncCallback(GetResponseCallback), request);
}
private void GetResponseCallback(IAsyncResult asynchronousResult)
{
var request = asynchronousResult.AsyncState as HttpWebRequest;
if (request != null)
{
try
{
WebResponse response = request.EndGetResponse(asynchronousResult);
using (Stream stream = response.GetResponseStream())
{
using (var reader = new StreamReader(stream, Encoding.UTF8))
{
var responseString = reader.ReadToEnd();
MessageBox.Show(responseString);
}
}
}
catch (WebException e)
{
// Handle exception
MessageBox.Show(e.Message);
}
}
}
public void SendPost(Uri uri, string json)
{
var webClient = new WebClient();
webClient.Headers[HttpRequestHeader.ContentType] = "application/json";
webClient.UploadStringCompleted += this.sendPostCompleted;
webClient.UploadStringAsync(uri, "POST", json);
}

Saving data in windows phone received from WCF/web service .

Saving data in windows phone received from WCF/web service .
The response may be received after sometime so how to handle this situation.
Saving data is no problem but How to handel if data is received late
You can use this code (show the code from my project):
public void sendPost(string postData, Action<MyResponse, Exception> callback, CreateResponse creater)
{
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(UrlRequest);
webRequest.Method = "POST";
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.Accept = "application/json";
webRequest.AllowAutoRedirect = true;
webRequest.BeginGetRequestStream(new AsyncCallback(getRequestStreamCallback), new Request()
{
HttpRequest = webRequest,
PostData = postData,
Url = UrlRequest,
CallBack = callback,
Creater = creater
});
}
private void getRequestStreamCallback(IAsyncResult asynchronousResult)
{
var request = (Request)asynchronousResult.AsyncState;
// End the stream request operation
Stream postStream = request.HttpRequest.EndGetRequestStream(asynchronousResult);
byte[] byteArray = Encoding.UTF8.GetBytes(request.PostData);
// Add the post data to the web request
postStream.Write(byteArray, 0, byteArray.Length);
postStream.Close();
// Start the web request
request.HttpRequest.BeginGetResponse(new AsyncCallback(getResponseCallback), request);
}
private void getResponseCallback(IAsyncResult asynchronousResult)
{
var request = (Request)asynchronousResult.AsyncState;
try
{
HttpWebResponse response;
// End the get response operation
response = (HttpWebResponse)request.HttpRequest.EndGetResponse(asynchronousResult);
Stream streamResponse = response.GetResponseStream();
StreamReader streamReader = new StreamReader(streamResponse);
var myResponse = streamReader.ReadToEnd();
streamResponse.Close();
streamReader.Close();
response.Close();
MyResponse response_obj = request.Creater.CreateResponseObj();
using (MemoryStream stream = new MemoryStream(Encoding.Unicode.GetBytes(myResponse)))
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(response_obj.GetType());
response_obj = (GYResponse)serializer.ReadObject(stream);
if (request.CallBack != null)
{
request.CallBack.Invoke(response_obj, null);
}
}
}
catch (WebException e)
{
if (request.CallBack != null)
{
request.CallBack.Invoke(null, e);
}
}
}
public void getInfo(string uid, Action<MyResponse, Exception> callback)
{
CreateResponse creater = new CreateResponseGetInfo();
string model = "User";
string method = "getInfo";
Params parametrs = new Params();
parametrs.Uid = uid;
//create yor request
string request = getRequestString(model, method, parametrs, Atoken);
sendPost(request, callback, creater);
}
So, you call method, which send request to web service postRequester.getInfo(uid, ResponseHandler) and use delegate for processing result.
private void ResponseHandler(MyResponse result, Exception error)
{
if (error != null)
{
string err = error.Message;
return;
}
else
{
var infoResponse = result as ResponseGetInfo;
if (infoResponse != null)
{
//result processing..
}
}
}
All the web requests you make in a Windows Phone app are Asynchronous. That means, you make a web request from your app and attach a handler to handle the response when it comes. In the response handler, you will have to take care of the response and do whatever you want with it.
Check this link Using WebClient and HttpWebRequest