I have a issue in implementing Error handling in Web-APi
[HttpGet]
public UserAccount Get()
{
throw new HttpResponseException(
new HttpResponseMessage(HttpStatusCode.InternalServerError)
{
Content = new StringContent("My Error Message"),
ReasonPhrase = "Critical Exception"
});
}
When I tried to call this method from my machine(site is hosted locally), it is working as expected. i.e I got the error message in response (plain text). But when I access the same url from another machine(LAN connected), response is IIS 500 internal error page. Here my problem is that, I am not getting the custom error message "My Error Message"
Any suggestions?
Add this to your web config:
<system.webServer>
<httpErrors errorMode="Detailed"/>
Related
I saw similar post Error Handling with WCF Service and Client Application to my question but I needed more help.
I have a MVC project with the WCF Service. I understand that WCF needs to throw a FaultException. But my question is what is the best way to show the error message created by an error in WCF. I just want to redirect all the errors (possibly all FaultException) to one error page (will be generic) but message will be different.
I also would like to use [HandleError] attribute so that I don't have to implement catching FaultException for all the methods calling the WCF service.
As you know how you can handle WCF exceptions but in my opinion this is better to observe these:
1-This not good idea to show user exactly exception message, this is better to show very understandable message for example "Operation get failed there is may problem with back-end service, try again or notify admin"
2- It's is boring end user to redirect to public error page.
3- This is better show the public prompt to user which tell user that the operation get failed exactly where the user do action not redirect it to another page.
4- At the end If you want to do what you want try these:
try
{
//Call your wcf
}
catch(Exception exp)
{
//Logging.Log(LoggingMode.Error, "You message , EXP:{0}...", exp.ToString());
Response.Redirect("~/ErrorPages/Oops.aspx?Error=WCfOperationFailed", false);
}
in your error page page_load:
switch (Request.QueryString["Error"].ToString())
{
case "WCfOperationFailed":
litError.Text = string.Format("<h2>Error!.</h2><br/><p>{0}.</p>",GetError());
break;
default:
break;
}
public string GetError()
{
Exception lastError = Server.GetLastError();
return lastError.ToString();
}
or you can redirect error message as a QueryString to error page and show it to user in Page_load like:
//in catch block
Response.Redirect("~/ErrorPages/Oops.aspx?Error="+exp.Message, false);
in error page Page_load :
txtError.Text = Request.QueryString["Error"].ToString();
However, you can trap errors that occur anywhere in your application by adding code to the Application_Error handler in the Global.asax file:
void Application_Error(object sender, EventArgs e)
{
Exception exc = Server.GetLastError();
if (exc is HttpUnhandledException)
{
// Pass the error on to the error page.
Server.Transfer("ErrorPage.aspx?Error="+exc.Message, true);
}
}
This link can be helpful there are some examples
Error Handling
In one of my method I have to return IHttpActionResult from there in Web API 2. When succeeded it returns Ok() either it returns BadRequest() with some message.
I am setting the message of BadRequest in the following way. But the problem is that I am unable to retrieve the error message from the called method. I am using Visual Studio 2013 Update 4 and the version is MVC 5.
return BadRequest("Error! Error adding the device");
Please help. Thanks in advance.
After through research and study I found the solution. As this is a method of Web API, I have called it through my website. I have called it like the following way where RequestUrl is the url of this Web API method. If there are parameter(s) in the method, we have to write it in querystring.
HttpResponseMessage Response = null;
Response = client.GetAsync(RequestUrl).Result;
var stream = Response.Content.ReadAsStreamAsync().Result;
// convert stream to string
StreamReader reader = new StreamReader(stream);
string text = reader.ReadToEnd();
We also can have the response type using the following code.
Response.ReasonPhrase
And in this way I can have the message of BadRequest as well Ok. BINGO !!
A custom error page could also cause your message not to appear. If your web.config file has something like the following, try removing it as it will intercept your 400 status errors: if you do have the following change existingResponse="Replace to existingResponse="PassThrough
<httpErrors existingResponse="Replace" errorMode="Custom">
<remove statusCode="404" subStatusCode="-1"/>
<error statusCode="404" prefixLanguageFilePath="" path="/myapppath/error404.aspx" responseMode="ExecuteURL"/>
</httpErrors
You have to set ReasonPhrase and wrap ResponseMessage to get an IHttpActionResult:
return this.ResponseMessage(new HttpResponseMessage
{
StatusCode = HttpStatusCode.BadRequest,
ReasonPhrase = ex.Message
});
I have an ASP.NET MVC 4 application and I want to redirect all HTTP 400 errors to my custom error page. I was searching an hours to find a solution though HTTP 400 error isn't handled like 404 error. There are many solutions that show how to escape 400(bad request error), i.e. to allow using special characters for example in url. But I wouldn't able to find some solution to catch the exception.
Please help me to catch somehow all HTTP bad requests and redirect them to my error page.
Never redirect users in case of errors, instead return a response body for the failed request. The feature of IIS (and ASP.NET) to redirect to an error page, I believe, is fundamentally wrong, incorrect, and against the HTTP specification (because then the error is being returned for the error page resource itself, not the original request. And if it's a web-browser the user has no way of retrying, because reloading the page will return the error page again, not retrying their original failed request, which is what they want).
Anyway...
A HTTP 400 response must be generated by your application code, it isn't something that will be done automatically. A bad request is typically used when informing non-human agents (i.e. web service clients, not web browsers) that their HTTP request was missing required values or had malformed values.
You can do this in MVC by having a base controller class for all of your controllers like so:
public abstract class BaseController : Controller {
protected ActionResult Http400(String message) {
Response.StatusCode = 400;
return View(message); // you need to define a view file called "Http400.aspx" (or cshtml if you're using Razor) in your application's shared views folder
}
}
so in your application logic:
public ActionResult Foobar() {
if( IsBadRequest() ) return Http400("Bad request, try again");
}
You could do something as simple as adding adding this to your web.config
<customErrors mode="RemoteOnly">
<error statusCode="400" redirect="errorpage.html"/>
</customErrors>
There is an action in my ASP.NET MVC controller that returns JSON data with a 400 Bad Request when invalid parameters are passed to the action.
[HttpDelete]
public ActionResult RemoveObject(string id) {
if(!Validate(id)) {
Response.StatusCode = (int)HttpStatusCode.BadRequest;
return Json(new { message = "Failed", description = "More details of failure" });
}
}
This works perfectly running under IIS or with the development test server launched from Visual Studio. After the project has been deployed to Azure the 400 Bad Request comes back without the JSON data. The content type has changed to 'text/html' and 'Bad Request' for the message.
Why is the behavior different under Azure?
Add the following entry to your 'web.config'.
<system.webServer>
<httpErrors existingResponse="PassThrough"/>
</system.webServer>
This will allow HTTP errors to pass through un-molested.
I've been struggling all day to implement error handling in my ASP.NET MVC 2 app. I've looked at a variety of techniques, but none work properly. I'm using MVC2 and .NET 4.0 (started the project before MVC3 was released; we'll upgrade after we deliver our initial release).
At this point, I'll be happy to properly handle 404 and 500 errors -- 403 (authorization required) would be great, too, followed by various other specific responses. Right now, I either get all 404s, all 500s, all 302s before the 404, or all 302s before the 500.
Here are my requirements (which should be pretty close to the basic requirements of HTTP):
If a resource is not found, throw a 404, and display a 404-specific page with the requested URL. DO NOT return an intermediate response code like 302. Ideally, keep the requested URL, rather than showing a new URL like /Error/NotFound -- but if the latter displays, be sure we didn't return a redirect response to get it.
If an internal server error occurred, throw a 500, and display a 500-specific error with some indication of what went wrong. Again, don't return an intermediate response code, and ideally don't change the URL.
Here's what I'd consider a 404:
Static file not found: /Content/non-existent-dir/non-existent-file.txt
Controller not found: /non-existent-controller/Foo/666
Controller found, but Action not found: /Home/non-existent-action/666
Controller and action found, but the action can't find the requested object: /Home/Login/non-existent-id
Here's what I'd consider a 500:
Post a bad value: POST /User/New/new-user-name-too-long-for-db-column-constraint
Non-data-related problem, like a Web Service endpoint not responding
Some of these problems need to be identified by specific controllers or models, and then the controllers should throw the appropriate HttpException. The rest should be handled more generically.
For 404 case #2, I tried to use a custom ControllerFactory to throw a 404 if the controller can't be found.
For 404 case #3, I've tried to use a custom base controller to override HandleUnknownAction and throw a 404.
In both cases, I get a 302 before the 404. And, I never get 500 errors; if I modify Web.config to put a typo in my Web Service endpoint, I still get a 302, then a 404 saying the URL (controller/action) which uses the Web Service can't be found.
I also get the requested URL as a(n unwanted) querystring param: /Error/NotFound?aspxerrorpath=/Home/non-existent-action
Both of these techniques came from http://www.niksmit.com/wp/?p=17 (How to get normal 404 (Page not found) error pages using ASP.Net MVC), pointed to from http://richarddingwall.name/2008/08/17/strategies-for-resource-based-404-errors-in-aspnet-mvc/
If in Web.config I have <customErrors mode="On" defaultRedirect="~/Error/Unknown" redirectMode="ResponseRedirect" />, I get the appropriate response code, but my Error controller never gets called. Taking out the redirectMode attribute gets me the MVC error views, but with an intervening 302 and a changed URL -- and always the same controller (Unknown = 500; if I change it to NotFound everything looks like a 404).
Here are some of the other things I've read and tried to implement:
http://www.davidjuth.com/asp-net-mvc-error-handler.aspx
http://sanjayuttam.com/wordpress/index.php/c-sharp/c-sharp-code-examples/error-handling-in-asp-net-mvc-1-part-2-of-2/
http://blog.hebbink.com/post/2010/12/14/NET-custom-404-error-page-returns-302-for-http-status.aspx
http://blog.dantup.com/2009/04/aspnet-mvc-handleerror-attribute-custom.html
http://weblogs.asp.net/scottgu/archive/2008/07/14/asp-net-mvc-preview-4-release-part-1.aspx
.. along with a bunch of StackOverflow posts.
Seems to me this sort of error handling is pretty basic to Web apps, and the MVC framework ought to have defaults that do this out of the box, and let people extend it to work otherwise. Perhaps they'll do it in a future release. In the meantime, can someone give me comprehensive details on how to implement proper HTTP responses?
Here's one technique you could use. Define an ErrorsController which will serve the error pages:
public class ErrorsController : Controller
{
public ActionResult Http404()
{
Response.StatusCode = 404;
return Content("404", "text/plain");
}
public ActionResult Http500()
{
Response.StatusCode = 500;
return Content("500", "text/plain");
}
public ActionResult Http403()
{
Response.StatusCode = 403;
return Content("403", "text/plain");
}
}
and then in Global.asax you could subscribe for the Application_Error event where you could log the exception and execute the corresponding action of the ErrorsController:
protected void Application_Error(object sender, EventArgs e)
{
var app = (MvcApplication)sender;
var context = app.Context;
var ex = app.Server.GetLastError();
context.Response.Clear();
context.ClearError();
var httpException = ex as HttpException;
var routeData = new RouteData();
routeData.Values["controller"] = "errors";
routeData.Values["exception"] = ex;
routeData.Values["action"] = "http500";
if (httpException != null)
{
switch (httpException.GetHttpCode())
{
case 404:
routeData.Values["action"] = "http404";
break;
case 403:
routeData.Values["action"] = "http403";
break;
case 500:
routeData.Values["action"] = "http500";
break;
}
}
IController controller = new ErrorsController();
controller.Execute(new RequestContext(new HttpContextWrapper(context), routeData));
}
And now all that's left is to start throwing proper exceptions:
public class HomeController : Controller
{
public ActionResult Index()
{
throw new HttpException(404, "NotFound");
}
}
For HTTP 404 errors (without redirects) take a look at my blog post on the subject. This might give you some good ideas:
http://hectorcorrea.com/blog/returning-http-404-in-asp-net-mvc/16
This doesn't answer your question, but it is important to note that HTTP status 500 indicates that something went wrong on the server, so your example:
POST /User/New/new-user-name-too-long-for-db-column-constraint
Is not valid grounds to throw a 500, its a data validation issue and should be handled by MVC data annotations or a jQuery validation framework or etc. Just showing an error message next to the TextBox saying "User Name too long" is much better.
This is a very old question. but I thought It's worth it if I introduce you to a much much cleaner way to handle Http Exceptions that I saw in dear "Jesse Webb's answer".
The solution is to use the httpErrors element of the system.webServer section:
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="404" subStatusCode="-1" />
<remove statusCode="500" subStatusCode="-1" />
<error statusCode="404" path="/Error/NotFound" responseMode="ExecuteURL" />
<error statusCode="500" path="/Error" responseMode="ExecuteURL" />
</httpErrors>
You also can log all exceptions in this way. "Read the "Jesse Webb's answer"".
This really feels much cleaner and also works as well as every other solution (without redirect).
Note: This only works work in IIS 7 and and newer. (Because of the httpErrors element which was recently added.