February 20, 2012 09:44 by
Scott
ASP.NET MVC 4 provides a new feature called Browser Overriding.Browser Overriding API helps us lets your application treat requests as if they were coming from a different browser (user agent) than the one they’re actually from.
Browser Overriding API provides few extension methods for HttpContext class, the method are part of BrowserHelpers class in System.Web.WebPages namespace.
The following helper method are use full from switching between one browser mode to other browser mode, overriding the actual browser etc.
- HttpContext.ClearOverriddenBrowser()
Removes any overridden user agent for the current request.
- HttpContext.GetOverriddenBrowser()
Returns an HttpBrowserCapabilitiesBase instance that corresponds to the user agent currently set for the request (actual or overridden). You can use this value to get properties such as IsMobileDevice, Type, Id, MajorVersion, MinorVersion, Tables, etc.
- HttpContext.GetOverriddenUserAgent()
Returns the request’s user agent override value, or the actual user agent string if no override has been specified.
- HttpContext.SetOverriddenBrowser(BrowserOverride browserOverride)
Overrides the request’s actual user agent value using the specified BrowserOverride enum value (BrowserOverride.Desktop / BrowserOverride.Mobile).
- HttpContext.SetOverriddenBrowser(userAgentString)
Overrides the request’s actual user agent value using the specified user agent.
- HttpContext.GetVaryByCustomStringForOverriddenBrowser()
February 14, 2012 07:03 by
Scott
In this blog post I will show how to set up custom error pages in ASP.NET MVC 3 applications to show user-friendly error messages instead of the (yellow) IIS default error pages for both “normal” (non-AJAX) requests and jQuery AJAX requests.
In this showcase we will implement custom error pages to handle the HTTP error codes 404 (“Not Found”) and 500 (“Internal server error”) which I think are the most common errors that could occur in web applications. In a first step we will set up the custom error pages to handle errors occurring in “normal” non-AJAX requests and in a second step we add a little JavaScript jQuery code that handles jQuery AJAX errors.
We start with a new (empty) ASP.NET MVC 3 project and activate custom errors in the Web.config by adding the following lines under <system.web>:
<customErrors mode="On" defaultRedirect="/Error">
<error redirect="/Error/NotFound" statusCode="404"/>
<error redirect="/Error/InternalServerError" statusCode="500"/>
</customErrors>
Note: You can set mode=”Off” to disable custom errors which could be helpful while developing or debugging. Setting mode=”RemoteOnly” activates custom errors only for remote clients, i.e. disables custom errors when accessing via http://localhost/[...]. In this example setting mode=”On” is fine since we want to test our custom errors. You can find more information about the <customErrors> element here.
In a next step we remove the following line in Global.asax.cs file:
filters.Add(new HandleErrorAttribute());
and add a new ErrorController (Controllers/ErrorController.cs):
public class ErrorController : Controller
{
public ActionResult Index()
{
return InternalServerError();
}
public ActionResult NotFound()
{
Response.TrySkipIisCustomErrors = true;
Response.StatusCode = (int)HttpStatusCode.NotFound;
return View("NotFound");
}
public ActionResult InternalServerError()
{
Response.TrySkipIisCustomErrors = true;
Response.StatusCode = (int)HttpStatusCode.InternalServerError;
return View("InternalServerError");
}
}
In a last step we add the ErrorController‘s views (Views/Error/NotFound.cshtml and Views/Error/InternalServerError.cshtml) that defines the (error) pages the end user will see in case of an error. The views include a partial view defined in Views/Shared/Error/NotFoundInfo.cshtml respectively Views/Shared/Error/InternalServerErrorInfo.cshtml that contains the concrete error messages. As we will see below using these partial views enables us to reuse the same error messages to handle AJAX errors.
Views/Error/NotFound.cshtml:
@{
ViewBag.Title = "Not found";
}
@{
Html.RenderPartial("Error/NotFoundInfo");
}
Views/Shared/Error/NotFoundInfo.cshtml:
The URL you have requested was not found.
Views/Error/InternalServerError.cshtml:
@{
ViewBag.Title = "Internal server error";
}
@{
Html.RenderPartial("Error/InternalServerErrorInfo");
}
Views/Shared/Error/InternalServerErrorInfo.cshtml:
An internal Server error occured.
To handle errors occurring in (jQuery) AJAX calls we will use jQuery UI to show a dialog containing the error messages. In order to include jQuery UI we need to add two lines to Views/Shared/_Layout.cshtml:
<link href="@Url.Content("~/Content/themes/base/jquery.ui.all.css")" rel="stylesheet" type="text/css" />
<script src="@Url.Content("~/Scripts/jquery-ui-1.8.11.min.js")" type="text/javascript"></script>
Moreover we add the following jQuery JavaScript code (defining the global AJAX error handling) and the Razor snippet (defining the dialog containers) to Views/Shared/_Layout.cshtml:
<script type="text/javascript">
$(function () {
// Initialize dialogs ...
var dialogOptions = {
autoOpen: false,
draggable: false,
modal: true,
resizable: false,
title: "Error",
closeOnEscape: false,
open: function () { $(".ui-dialog-titlebar-close").hide(); }, // Hide close button
buttons: [{
text: "Close",
click: function () { $(this).dialog("close"); }
}]
};
$("#InternalServerErrorDialog").dialog(dialogOptions);
$("#NotFoundInfoDialog").dialog(dialogOptions);
// Set up AJAX error handling ...
$(document).ajaxError(function (event, jqXHR, ajaxSettings, thrownError) {
if (jqXHR.status == 404) {
$("#NotFoundInfoDialog").dialog("open");
} else if (jqXHR.status == 500) {
$("#InternalServerErrorDialog").dialog("open");
} else {
alert("Something unexpected happend :( ...");
}
});
});
</script>
<div id="NotFoundInfoDialog">
@{ Html.RenderPartial("Error/NotFoundInfo"); }
</div>
<div id="InternalServerErrorDialog">
@{ Html.RenderPartial("Error/InternalServerErrorInfo"); }
</div>
As you can see in the Razor snippet above we reuse the error texts defined in the partial views saved in Views/Shared/Error/.
To test our custom errors we define the HomeController (Controllers/HomeController.cs) as follows:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult Error500()
{
throw new Exception();
}
}
and the corresponding view Views/Home/Index.cshtml:
@{
ViewBag.Title = "ViewPage1";
}
<script type="text/javascript">
$function () {
$("a.ajax").click(function (event) {
event.preventDefault();
$.ajax({
url: $(this).attr('href'),
});
});
});
</script>
<ul>
<li>@Html.ActionLink("Error 404 (Not Found)", "Error404")</li>
<li>@Html.ActionLink("Error 404 (Not Found) [AJAX]", "Error404", new { }, new { Class = "ajax" })</li>
<li>@Html.ActionLink("Error 500 (Internal Server Error)", "Error500")</li>
<li>@Html.ActionLink("Error 500 (Internal Server Error) [AJAX]", "Error500", new { }, new { Class = "ajax" })</li>
</ul>
To test the custom errors you can launch the project and click one of the four links defined in the view above. The “AJAX links” should open a dialog containing the error message and the “non-AJAX” links should redirect to a new page showing the same error message.
Summarized this blog post shows how to set up custom errors that handle errors occurring in both AJAX requests and “non-AJAX” requests. Depending on the project, one could customize the example code shown above to handle other HTTP errors as well or to show more customized error messages or dialogs.
When thinking about error handling in ASP.NET MVC 3 applications you should take a look at ELMAH (Error Logging Modules and Handlers for ASP.NET), a tool that logs/handles errors on server side and which works perfectly in combination with the approach shown above.
February 7, 2012 07:49 by
Scott
ASP.NET MVC3 includes a new class HttpNotFoundResult in System.Web.Mvc namespace.
HttpNotFoundResult: Instance of HttpNotFoundResult class indicates to client(browser) that the requested resource was not found. It returns a 404 HTTP status code to the client. Generally we return 404 status code if a requested webpage is not available. In case of MVC applications we return 404 status code is in terms of resources, for example we are searching for particular user profile in the portal, if the user profile is not found, we can return 404.
How to return 404 status code from a MVC application?
First way is to instantiate HttpNotFoundResult class and return the object.
public ActionResult Index()
{
var result = new HttpNotFoundResult();
return result;
}
Next alternative is to makes use of HttpNotFound() helper method of the Controller class which returns the HttpNotFoundResult instance.
public ActionResult Index()
{
return HttpNotFound();
}
we can return 404 along with custom status code description,using the overloded version of HttpNotFound(string statusDescription).
public ActionResult Index()
{
return HttpNotFound("can not find requested resource");
}