MVC4 – Suraj | Coding Passion Tue, 09 Oct 2018 07:03:49 +0000 en-US hourly 1 https://wordpress.org/?v=4.9.8 Unobstrusive ajax and handle unauthorized request in MVC /unobstrusive-ajax-and-handle-unauthorized-request-in-mvc/ /unobstrusive-ajax-and-handle-unauthorized-request-in-mvc/#respond Tue, 05 Apr 2016 10:18:26 +0000 /?p=580 Introduction

In this article I will be sharing a basic stuff which comes handy in MVC applications. The HTML helpers provided by the Razor are smart enough to understand and process the work as required.
We will be discussing in brief about the Ajax.BeginForm, which has few concepts hidden within. When we face the difficulty or the issue, we explore and resolve. Same has happened recently with me. So lets start exploring what the hidden secrets are, which actually are very few.

Adding Unobstrusive- Ajax JS

This can be added from the Nuget package manager directly. I find adding from the Package Manager console easy. The script goes like below:

Install-Package jQuery.Ajax.Unobtrusive

Snippet & Learning

AjaxExtensions.BeginForm is a part of System.Web.Mvc.Ajax namespace under the System.Web.MVC assembly. When used in the response it writes the HTML

tag. Ajax, as we know is Asynchronous Javascript and XML, the word asynchronous plays the trick actually. That means the call will be done asynchronously in some other thread, without hampering or halting the current executing thread for better user experience and performance. Thus, the ajax call we used to write through jQuery, can be done by the MVC HTML helpers now.
One important point to remember here is we need to have the unobstrusive-ajax.js file in order for the Ajax.BeginForm to work in the actual manner.
The Ajax.BeginForm has three options attached to it.
@using (Ajax.BeginForm("ACTION", "CONTROLLER", new AjaxOptions { UpdateTargetId = "TARGETID" ,OnSuccess="PostSuccess"}))
{
   <div id="TARGETID"></div>
   // Do anything you would like to.
}

Lets understand the properties it possesses.
The first param to the Ajax.BeginForm is Action Method, the action to which we will be posting or getting the results.
The second param is Controller, the route controller in which the Action Method is specified. The route table in turn configures accordingly.
The third is the important property of the Ajax.BeginForm as it gives us the different options in order to track and show the response, even manipulate the response as well.

  • UpdateTargetId:- This property is used to track the ‘id’ where the ajax response will be displayed.
  • OnSuccess, OnFailure, OnComplete, OnBegin:- The second part of the option is the track functions. We can use the the functions to track the event and update the UI accordingly. The methods are self explanatory so, I not being stupid to explain the same. 😛
  • HttpMethod:- This again is self explanatory, it allows the POST GET to be specified explicitly.
  • AllowCache:- This method in ajax allows to either cache the response or not. By default it caches the identical request’s response. So to avoid any kind of caching, we can use the Attribute [OutputCache(NoStore = true, Duration = 0, VaryByParam = “*”)]

These were few of the important properties discussed, which are frequently used.
Now another issue we face is when we have a session ended for any user, but the user is still on the web page, then we find that the login page loads in the partial part of the page only, not the whole page is reloaded to the Login page, which is really weird from any user point of view. This can easily be done and accomplished by changing the UpdateTargetId to the body or supplying any id to the body tag.
But sometimes we have to handle the unauthorized access from the user during any ajax calls. So, incase (everytime now in MVC projects Authorize attribute and its virtual methods are overridden), inside the Custom Authorize attribute, we modify/override the HandleUnauthorizedRequest and handle the Ajax calls that are unauthorized. The code goes below:

protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
        {
            if (filterContext.HttpContext.Request.IsAjaxRequest())
            {
                filterContext.Result = new JsonResult
                {
                    JsonRequestBehavior = JsonRequestBehavior.AllowGet,
                    Data = new { redirectTo = FormsAuthentication.LoginUrl }
                };
            }
            else
            {
                base.HandleUnauthorizedRequest(filterContext);
            }
        }

filterContext.HttpContext.Request.IsAjaxRequest() is doing the trick here, tracking whether the request coming from the client is Ajax request or the normal request.
redirectTo = FormsAuthentication.LoginUrl This takes the default login URL from the app settings in Web.config file. Thus now the result of the context will be present in the current context and can be tracked by the Onsuccess method. The code can be seen below:

function PostSuccess(result) {
    if (result.redirectTo) {
        window.location.href = result.redirectTo;
    }
}

This is a simple part, we can also do the same tracking the reference of the result context and manipulate.

Conclusion

I tried to cover a basic stuff in the MVC application, which we use frequently in our application, sometimes scratch our head to get a proper understanding and solution to a simple problem. I hope this has helped some way. Any suggestions or more interesting facts are more than welcome.
Keep learning and keep sharing.

]]> /unobstrusive-ajax-and-handle-unauthorized-request-in-mvc/feed/ 0 Url routing in MVC application /url-routing-in-mvc-application/ /url-routing-in-mvc-application/#comments Sun, 27 Sep 2015 10:04:55 +0000 /?p=419 Introduction

There exists an assumption that there is a direct relationship between the requested URLs and the files stored on the server. But does this make sense in an MVC application, where requests are processed by action methods and controllers and there is no relation to files on the server (disk).
MVC applications use routing system in order to track the request and give response to the users. The routing system helps create patterns of URLs, that to pattern of our wish. The routing system does the following job, Incoming URL examination- It checks the url requested and it intends the controller and action and based on the url, it redirects the controller based on the client request. This is a very interesting and an important subject of discussion. Once we create an MVC application, it is already configured to use Asp.Net routing system. There are four sections that are any way required relevantly for the routing system in the application. They are:

  • system.web httpModules:- These are required to configure the modules within an application. Http Modules are assemblies that are called on every request made to the application.
  • system.web.httpHandlers:- This runs in response to the request made to the application.

The above mentioned are required for the routing system and should be present in the configuration of the application. We need to make sure the above configurations exist in our application.

Lets start with snippets

public class RouteConfig {
    public static void Registerroutes (RouteCollection routes) {
         routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
         routes.MapRoute (
            name : "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
}

Now, this RouteConfig.cs resides inside the App.Config folder. The RegisterRoutes method inside the RouteConfig.cs gets called from the heart of the MVC application i.e. Global.asax.cs, which sets the core MVC features when the application is started. The called RegisterRoutes method gets called inside Global.asax.cs as follows:

RouteConfig.RegisterRoutes(RouteTables.Routes);

To the method as we can see the parameter is passed i.e. RouteTables.Routes which is a collection routes or the instance of the RouteCollection.cs. To register adding a new route, we need to register inside the RegisterRoutes method as below:

Route demoRoute = new Route("{controller}/{action}", new MvcRouteHandler());
routes.Add("DemoRoute", demoRoute);

Lets understand the above snippet, Here a new route named demoRoute is being created. MvcRouteHandler() is also passed to the constructor. This extends the IHttpHandler and passes the request. routes , the object above is an instance of the RouteCollection class which is passed from the Global.asax.cs. There is another easy way of registering routes, i.e. by using MapRoute method defined by RouteCollection class like below:

routes.MapRoute("RouteName", "{controller}/{action})

One thing to note here is, if the route incase donot match any of the routes in the RouteCollection, then the error is thrown to the user. generally, default route is set to Index as action. Then, the url with https://demosite/home will also get the user to the Index action method. If both the controller and action are provided to the routes, then routes match url with no segments (if default is defined in the RouteConfig). Generally, the controller if only used in the url, then the Controller’s action Index method is called i.e.

https://demosite.com/Admin

This would call the Admin Index method. If any other action method is called, then similarly based on the segments in the url requested, the action in the specified controller is called.

Static URL Segments

There is this concept of static url segments. This is rarely used but the concept is quite interesting. Here, the route is registered inside RouteConfig like below:

routes.MapRoute(""), "X{controller}/{action}");

Here, what happens is whatever is present after X or suffixed to X, that controller and action gets called. For example, https://demosite.com/XAdmin/Index, here what happens is the controller Admin and the Action Index is called.
There is a concept of Route Ordering as well, in which in the order the routes are defined in the RouteCollection, the same order the route mapping is done. I.E. when a URL requests is made to the application, the route config maps the route defined until a match is found in the same order routes are defined.
Another interesting fact to notice here, Suppose we have a controller named “Admin” and sometime in the future we require to modify the name of that controller. Now if we donot modify our RouteConfig, we would get a 404 NOT FOUND error. To avoid this we do the following modification in the Route.Config.cs:

public static void RegisterRoutes (RouteCollection routes) {
   routes.MapRoute ("Admin","Admin/{action}",
      new {controller="Home"});
  }

Thus, when a request as /Admin/Index comes to the server, the controller called is /Home/Index, avoiding the 404 error page. Since, there is no segment variable supplied, so default provided is used. The same can be done in case of an Action as well, i.e. if an action is removed from the controller, we can have a default route check for that action as well and redirect to the specified and default route URL if not found. Like as below:

routes.MapRoute("Admin","Admin/department",
    new {controller = "Admin",action = "Index"});

Defining Custom Segment Variables

Controller and Action are common part of any url request to the MVC application and these would be considered as the in-built segment variables. But there are other segment variables that can be customized for the service requests. Lets take a look at a snippet:

public static void RegisterRoutes(RouteCollection routes) {
    routes.MapRoute("RouteDemo", "{controller}/{action}/<b>{id}</b>")
        new {controller = "Admin" , action="GetDept", id = "DefaultID"});
}

Here we can see we have declared a custom varialble “id” with a default value. Thus any url request with two or three segment variables would work out. If the id is not specified explicitly in the URL, then it takes the default id value.
Usually,the third segment variable is used to fetch the parameter to be utilized in the service methods.

public ActionResult GetDepartment(int id) {
  //Used id to get the particular department.
}

Here if id is not provided in the URL, then it searches using default id specified and may return null. Thus, to avoid, we can also defined the third segment variable to be optional, so that we have action to also return result if no id is specified in the URL.

routes.MapRoute("OptionalRoute", "{controller}/{action}/{id}",
     new {controller = "Admin", action = "GetDept", id = <b>UrlParameter.Optional</b> });

Thus the UrlParameter.Optional makes the third segment variable optional and rund through without any default variables as well.

Prioritizing Controllers with same name using name spaces

This is a very interesting and strong concept which can be really handy, when working on a huge MVC application. Lets take a scenario to understand this, suppose we have a controller name “Home “inside the controllers folder and another controller with same name “Home” inside another folder say “AddonControllers”. So when we run the project and hit the URL /Home/Index, then the routing and mapping that searches the URL requested, will be in ambiguity as it fetches two controllers with same names. Thus this will throw an error with the exception message as :

Multiple types were found that match the controller named “Home”. This can happen if the route that services this request (‘{controller}/{action}/{id}’) does not specify the namespace to search for a controller that matches the request..

Thus, from the error message itself we can get that this error can be resolved easily by specifying the name space for which you want to prioritize the search when URL request is made to the server. Lets see how:

routes.MapRoute("DemoRoute", "{controller}/{action}/{id}",
      new {controller = "Home", action = "Index", id = <b>UrlParameter.Optional</b> },
       <b> new []{"URLsAndRoutes.AddonControllers"}</b>);

Here, specifying the new array of strings and saying the MVC routing to search for the controller everytime in the AddonControllers or the specified namespace first and if not found then move into the controllers folder to search for the match of the URL request. This really would of high use when the requirement is as such.

Conclusion & Points of Interests

Thus here we discussed about one of the critical concepts of MVC. Routing and pipelining is a mandatory concept to know to start with learning MVC. using MVC application and not using Routing is not wise. There are opportunities to manipulate and customize the Routing system, so it is always advisable to use Routing whenever MVC application is in picture. The URL segment variables Controllers, Actions and parameters are required to customize the URLs to th convinience of the end users. The routing can narrow down the search of the routes if the maximum hit URL requests are ordered highly in the Route Collection.

References

Asp.NET MVC Professional by Adam Freeman.

]]>
/url-routing-in-mvc-application/feed/ 1