Response.addHeader causes 500 (Internal Server Error) - c#

I have written a Login WebMethod ,if the details are ok i want to redirect to another page.
this is my code :
[WebMethod]
public String Login(String email, String password){
String result=WSUtils.GetData("check_login", email, password);
if (result.Equals("True")){
Context.Response.Clear();
Context.Response.Status = ""+System.Net.HttpStatusCode.Redirect;
Context.Response.AddHeader("Location", "/admin/index.html");
Context.Response.TrySkipIisCustomErrors = true;
Context.Response.End();
}
return result;
}
this code causes 500 (Internal Server Error)
thank you

Your function is trying to do too much. It is being called as a WebMethod that returns a string, but you are trying to redirect inside it. The problem is that redirecting inside this kind of function doesn't make sense. Whatever called Login only knows about the string result. It could be said that the return type of the function represents a "contract" between the client and the server. By redirecting inside the function you are breaking this contract and doing something unexpected that the client can't interpret, and the server infrastruction that handles the WebRequest can't handle.
The proper way to do this is to have your Login function stick to the "contract", just return the result. It should be the responsibility of the calling code to interpret the result of that code, by parsing the string result, and taking action on it.
To do this, remove the entire "if" block from your server call, and change the code on the client to look (something) like this:
if (myWebServiceClient.Login(email, password) == "True")
{
//I logged in, do success stuff here
}
else
{
//Display some kind of login failed message
//Redirect here
}

Related

ASP.NET C# Response.Write doesn't display message

So I am told just by using Javascript inside the Response.Write method, I can display an alert/message box on ASP.NET C#.
Using Response.Write("<script>alert('Data inserted successfully')</script>") as the template given in other answers.
When I first attempted to use it, it worked, displaying the message and redirecting me sucessfully. Since then, it has not worked, I only changed the message to display and also where the redirect URL would go after. Logically it is working as it is taking me back to the application form, it just isn't displaying the message.
Can anyone explain why it suddenly doesn't work?
Code;
public ActionResult UpdateApplication(int ApplicationId, ApplicationEdit applicationEdit)
{
if(applicationEdit.Firm == false)
try
{
applicationService.UpdateApplication(applicationEdit, ApplicationId);
return RedirectToAction("GetUser", "User", new { ApplicationId = applicationEdit.ApplicationId });
}
catch
{
return View();
}
else
{
Response.Write("<script language=javascript>alert('Sorry, You can only have 1 firm application to send off, please update the old application and untick firm option on other application first.')</script>");
return RedirectToAction("UpdateApplication", new { ApplicationId = applicationEdit.ApplicationId });
}
}
Because you're redirecting the user:
return RedirectToAction("UpdateApplication", new { ApplicationId = applicationEdit.ApplicationId });
This returns a redirect HTTP code to the browser (HTTP 307 or 308 I imagine) which tells the browser to direct the user to the specified URL. Since the browser knows it's redirecting the user, it has no reason to render any content in the response.
Either return content to be rendered in the browser or return a redirect response, but not both. If you return the view instead then you should see your <script> element in the resulting response. If you want to redirect then any message you want to display to the user should be on that next page, not in the current response.
As an aside, using Response.Write in an ASP.NET MVC application is pretty much always the wrong approach. Any client-side code should be in or referenced by the view, and you can use data on the view's model to conditionally render or not render that content.

Server cannot set status after HTTP headers have been sent - ELMAH

I have been receiving this error through ELMAH. Even though the program completes it's intended actions, I still receive this error through ELMAH and I'd like to know why and to fix it. I've gone through other threads and tried to use those suggestions but nothing I've read so far doesn't seem to work.
It's intended action is to create an excel document and then redirect the user to the page they were just on.
ActionResult:
public ActionResult ExportClaimNumberReport(int ClientID, string ClaimNo) {
ClaimNumberViewModel model = ClaimNumberReport(ClientID, ClaimNo);
CreateExcelFile.CreateExcelDocument(
model.ReportData.ToList(),
model.ReportDescription + (".xlsx"),
HttpContext.ApplicationInstance.Response);
ViewBag.client = client;
Response.Buffer = true;
Response.Redirect(Request.UrlReferrer.ToString());
if (!Response.IsRequestBeingRedirected) {
Response.Redirect("/Error/ErrorHandler");
}
return RedirectToAction("ErrorHandler", "Error");
}
If you need anymore info, just let me know
You will get the error because you are doing 2 redirects.
Once here
Response.Redirect(Request.UrlReferrer.ToString());
And then again here:
return RedirectToAction("ErrorHandler", "Error");
So the first redirect will write a redirect header to the response stream, then the second would try to do it again, but obviously you can't send http headers to the browser twice so it throws an exception. However the user won't notice because by the time the exception is thrown the browser has already been told to redirect elsewhere.
What you want to do is just call the Redirect method as the return statement from your controller action.
So replace all this:
Response.Redirect(Request.UrlReferrer.ToString());
if (!Response.IsRequestBeingRedirected) // this would always be false anyway
{
Response.Redirect("/Error/ErrorHandler");
}
return RedirectToAction("ErrorHandler", "Error");
With this:
return Redirect(Request.UrlReferrer.ToString())
Although why you are redirecting the browser back to the referring page is unclear.

How to use redirect (url) method in a class library?

I am trying to build a web site which uses survey monkey API methods to show data, for that I am building a class library in which I will call one(only one from some controller) method which should do the oauth of the user.(I was successful with the 3 step process mentioned in the survey monkey website) but now I want to call only one method from the controller to a method in class library which will do the oauth of the user and sets the token which can later be used for API methods. My code is like this in the class library:
HttpContext.Current.Response.Redirect(urlToAuthorize);
//what should be here (I should wait till the user gives credentials and authorize so that I can get the query string)
string tempAuthCode = HttpContext.Current.Session["code"].ToString();
if (!verifyRedirectedTempCode(tempAuthCode))
{
return "Not a valid Token";
}
else
{
try
{
var webRequest = GetWebRequestForHttpPostOfSurveyMonkeyToken(ApiKey,ClientSecret,tempAuthCode,RedirectUri,ClientId,GrantType,ContentType,WebRequestMethod);
using (HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse())
{
string tokenJson = new StreamReader(response.GetResponseStream()).ReadToEnd();
AccessToken accesstokenObj = JsonConvert.DeserializeObject<AccessToken>(tokenJson);
return accesstokenObj.Token.ToString();
}
}
catch
{
return null;
}
}
}
After redirecting its not waiting for the user to authorize.So,its not working exactly as I am thinking. How to wait till the User authorize and collect this query string? It should be done in class library itself.
You can't handle it like this. OAuth is a two-stage process. You redirect to the OAuth provider and then once the user authorizes there, they redirect back to your site, where you pickup where you left off.
That means you need two actions for this: one to initiate the process and one to receive the payload from the provider after authorization.

Exception from MVC API to MVC site gives error

I have created an MVC (4) Web API which works fine. It has a simple login-method that throws an exception when the user cannot be found.
Besides the API I created a simple website that calls the API by HttpClient:
public T ExecutePost<T>(string apiUrl, IEnumerable<KeyValuePair<string, string>> postData) {
HttpContent content = null;
if (postData != null)
content = new FormUrlEncodedContent(postData);
var a = _client.PostAsync(apiUrl, content).ContinueWith(httpResponseMessage =>
JsonConvert.DeserializeObject<T>(httpResponseMessage.Result.Content.ReadAsStringAsync().Result)
);
return a.Result;
}
You can call this method as
ExecutePost<User>("url_to_controller_action_api", list_with_keys_and_values_to_post)
When this method calls the API with the postData-fiels username and password (both are correct and known by the system) an object called User will be returned... Works like a charm.
When I call this method with the wrong username and/or password, the API throws an exception (User not found), but the method ExecutePost throws an exception aswell and the web page shows a nice, yellow-isch, red-letter page with errors that the normal user does not understand. The reason is easy: The data sent back from the API is not the same as the data that can be put in the object User.
So, what I would like to do is deserialize the exception, from the API, in an object called Error and return that to the controller of the MVC website, so I can put the error "User not found" on the page with the correct design of the site.
What is the best way to do this? Try-catch in all actions? Doesn't feel right to me... So suggestions are more than welcome.
Most things I found were API-side stuff, but I want to fetch and handle the exception on the site-side.
Thanks in advance
On your Web API when you detect an invalid login, make sure that an HttpResponseException gets thrown with a status code of 401 (HttpStatusCode.Unauthorized).
//login failed:
var resp = new HttpResponseMessage(HttpStatusCode.Unauthorized)
{
Content = new StringContent("Invalid Username or password")
};
throw new HttpResponseException(resp);
In your calling code, you can then first check if httpResponseMessage.StatusCode==HttpStatusCode.OK before you attempt to deserialise the response into a User.
var a = _client.PostAsync(apiUrl, content).ContinueWith(httpResponseMessage => {
if (httpResponseMessage.Status!=HttpStatus.OK)
{
string ErrorMessage = httpResponseMessage.Result.Content.ReadAsStringAsync();
//and whatever you want to do with that error message here
}
else
{
try
{
var user = JsonConvert.DeserializeObject<T>(httpResponseMessage.Result.Content.ReadAsStringAsync().Result);
}
catch(Exception ex)
{
//honest to goodness unrecoverable failure on the webapi.
//all you can do here is fail gracefully to the caller.
}
}//endif (Status OK)
}//end anonymous function
);
If it's not a 200 then you can execute a second check to see if it's a 401 (and have some specific handling for invalid login) or a more general 500 (something went wrong on the server), etc, and get the actual error message of the exception ("Invalid Username or password") to send back to the client:
var errorMessage = httpResponseMessage.Content.ReadAsStringAsync().Result;
Finally, even if it is 200 then you should still try...catch the deserialisation operation so you can gracefully handle any issues with the returned data, if for whatever reason the data can't be turned into a User object.

Got bad request error for a DELETE REST web service

In my interface I defined:
[OperationContract]
[WebInvoke(Method = "DELETE",
UriTemplate = "deleteAsset/{asset_id}")]
void deleteAsset(string asset_id);
My implementation is as follows:
public void deleteAsset(string asset_id)
{
using (DataClassesDataContext thisContext = new
DataClassesDataContext(ConfigurationManager.ConnectionStrings
["mgatewayConnectionString"].ConnectionString))
{
var result =
thisContext.spGetAssetById(Convert.ToInt32(asset_id)).FirstOrDefault();
if (result != null)
{
thisContext.spDeleteAsset(Convert.ToInt32(asset_id));
thisContext.spDeleteModuleAssetLink(Convert.ToInt32(asset_id));
}
}//using
}
I use RESTClient for Firefox for testing. I chose DELETE from the Method dropdown list and entered the url: localhost:57518/Service.svc/deleteAsset/127 and hit "Send" button. Then I got this error. I got the following error message:
400 Bad Request
The server encountered an error processing the request.
The problem is probably not in the code you've posted.
a 400 error should generally only happen if you send a malformed http request. So whatever way you're testing it, the web server is rejecting it befire it hits your method.
where is it happening? does it reach the "deleteAsset" methid?
Also, why are you checking if the asset exists before deleting? It seems like an unnecessary overhead. Cant you just run the delete command and if it exists it will be deleted, otherwise nothing will happen. If you need to know if something was actually deleted or not, get the affected rows from the delete command.

Categories

Resources