Monday, June 9, 2014

ASP.NET MVC AJAX error handling through filters and jQuery

Consider a scenario where you make an AJAX request in ASP.NET MVC through jQuery, i.e. $.ajax.  If you want to handle server side validations/exceptions and trap them in "error" callback of $.ajax, you can do it in a slick way:

1) Create a filter attribute:

public class ClientErrorAttribute : System.Web.Mvc.FilterAttribute, System.Web.Mvc.IExceptionFilter
    {
        public void OnException(ExceptionContext filterContext)
        {
            var response = filterContext.RequestContext.HttpContext.Response;
            response.Write(filterContext.Exception.Message);
            response.ContentType = MediaTypeNames.Text.Plain;
            filterContext.ExceptionHandled = true;
        }
    }

2) Apply filter to controller/action

[ClientError]
public class HomeController : Controller
{

}

3) Throw exceptions

[HttpGet]
public JsonResult CheckLogin()
{
 if (!User.IsLoggedIn)
 {
  throw new Exception("You are not authorised to perform this operation");
 }
}

4) Catch exceptions in jQuery

$.ajax({
    type: "post", url: "/SomeController/SomeAction",
    success: function (data, text) {
        //...
    },
    error: function (request, status, error) {
        alert(request.responseText);
    }
});

Saturday, May 24, 2014

The name 'model' does not exist in current context

I recently installed Visual Studio 2013 and updated my MVC3 application to MVC4 by following these steps.  I noticed that my MVC3 project disabled the intellisense for @model as well as other c# code including LINQ.  

Solution:

Create a web.config in the "Views" folder and add following configurations:

<?xml version="1.0"?>
 
<configuration>
  <configSections>
    <sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
      <section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
      <section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
    </sectionGroup>
  </configSections>
  <system.web.webPages.razor>
    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    <pages pageBaseType="System.Web.Mvc.WebViewPage">
      <namespaces>
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Routing" />
      </namespaces>
    </pages>
  </system.web.webPages.razor>
 
  <system.web>
    <pages
        validateRequest="false"
        pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
        pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
        userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
      <controls>
        <add assembly="System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc" tagPrefix="mvc" />
      </controls>
    </pages>
  </system.web>
 
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
 
    <handlers>
      <remove name="BlockViewHandler"/>
      <add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" />
    </handlers>
  </system.webServer>
</configuration>

Friday, April 25, 2014

Call a method after multiple AJAX requests are finished through jQuery

You may face a situation where you need to make multiple AJAX requests and call your function after all those requests are completed.

jQuery provides a way to handle this neatly:


$.when($.ajax( "/page1" ), $.ajax( "/page2" ) ).then(function( a1, a2)
{
    // a1 and a2 are arguments resolved for the page1 and page2 ajax requests
    // Each argument is an array with the following structure: [ data, statusText,jqXHR ]
});

Friday, April 18, 2014

CSS media queries for different Internet Explorer versions

/* IE6/7 uses media, */
@media, { 
.container { color: green; } 
.item { color: red; }
} 

/* IE8 uses \0 */
@media all\0 { 
.container { color: brown; }
.item { color: orange; }} 

/* IE9 uses \9 */
@media all and (monochrome:0) { 
.container { color: yellow\9; }           .
.item { color: blue\9; }} 

/* IE10 and IE11 both use -ms-high-contrast */
@media all and (-ms-high-contrast:none)
 {
 .foo { color: green } /* IE10 */
 *::-ms-backdrop, .foo { color: red } /* IE11 */
 }

Tuesday, April 8, 2014

JSONP calls in ASP.NET MVC

JSONP is "JSON with padding".  It is used to access or transfer data across the domains.  The code below is used to access JSONP data from a remote server and fetch the results in ASP.NET MVC

public ContentResult FetchData()
        {
            string signedUrl = ""; //URL to fetch jsonp data from
            WebRequest request = (HttpWebRequest)WebRequest.Create(signedUrl);
            request.Method = WebRequestMethods.Http.Get;
            string result = string.Empty;

            using (var response = (HttpWebResponse)request.GetResponse())
            {
                using (var reader = new StreamReader(response.GetResponseStream()))
                {
                    result = reader.ReadToEnd();
                }
            }

            return Content(result, "application/javascript");
        }

Tuesday, March 25, 2014

Make the layout of controls same in all the browsers - UniformJS

Most of the developers must have faced an issue from their client to make the layout of the controls similar in all the browsers.

I recently came across a beautiful and simple plugin which would take care of the UI just by a single line of code.

The implementation is very simple:
<!-- Make sure your CSS file is listed before jQuery -->
<link rel="stylesheet" href="uniform.default.css" media="screen" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.min.js"></script>
<script src="jquery.uniform.js"></script>]
// Style everything
$("select, input, a.button, button").uniform();

jQuery cross domain requests with JSONP

jQuery has a provision to make a cross domain AJAX request (GET) and fetch data in JSONP format.

$.ajax({
            type: 'GET',
            url: 'URL to access data',
            contentType: "application/json",
            crossDomain: true,
            cache: true,
            dataType: 'jsonp',
            success: function (result) {
            },
            error: function (e) {
                console.log(e.message);
            }
        });



Even if there is an error handler attached to the ajax call above, cross domain requests won't    handle any error or exceptions.  This is a limitation for jQuery JSONP calls.