top button
Flag Notify
    Connect to us
      Site Registration

Site Registration

ASP.NET MVC - Actions

+1 vote
492 views

ASP.NET MVC Action Methods are responsible to execute requests and generate responses to it. By default, it generates a response in the form of ActionResult. Actions typically have a one-to-one mapping with user interactions.

For example, enter a URL into the browser, click on any particular link, and submit a form, etc. Each of these user interactions causes a request to be sent to the server. In each case, the URL of the request includes information that the MVC framework uses to invoke an action method. The one restriction on action method is that they have to be instance method, so they cannot be static methods. Also there is no return value restrictions. So you can return the string, integer, etc.

Request Processing

Actions are the ultimate request destination in an MVC application and it uses the controller base class. Let's take a look at the request processing.

  • When a URL arrives, like /Home/index, it is the UrlRoutingModule that inspects and understands that something configured within the routing table knows how to handle that URL.

Request Processing

  • The UrlRoutingModule puts together the information we've configured in the routing table and hands over control to the MVC route handler.

  • The MVC route handler passes the controller over to the MvcHandler which is an HTTP handler.

  • MvcHandler uses a controller factory to instantiate the controller and it knows what controller to instantiate because it looks in the RouteData for that controller value.

  • Once the MvcHandler has a controller, the only thing that MvcHandler knows about is IController Interface, so it simply tells the controller to execute.

  • When it tells the controller to execute, that's been derived from the MVC's controller base class. The Execute method creates an action invoker and tells that action invoker to go and find a method to invoke, find an action to invoke.

  • The action invoker, again, looks in the RouteData and finds that action parameter that's been passed along from the routing engine.

Types of Action

Actions basically return different types of action results. The ActionResult class is the base for all action results. Following is the list of different kind of action results and its behavior.

Sr.No. Name and Behavior
1

ContentResult

Returns a string

2

FileContentResult

Returns file content

3

FilePathResult

Returns file content

4

FileStreamResult

Returns file content

5

EmptyResult

Returns nothing

6

JavaScriptResult

Returns script for execution

7

JsonResult

Returns JSON formatted data

8

RedirectToResult

Redirects to the specified URL

9

HttpUnauthorizedResult

Returns 403 HTTP Status code

10

RedirectToRouteResult

Redirects to different action/different controller action

11

ViewResult

Received as a response for view engine

12

PartialViewResult

Received as a response for view engine

Let’s have a look at a simple example from the previous chapter in which we have created an EmployeeController.

using System;
using System.Collections.Generic;
using System.Linq;

using System.Web;
using System.Web.Mvc;

namespace MVCControllerDemo.Controllers {
   public class EmployeeController : Controller{
      // GET: Employee
      public ActionResult Search(string name){
         var input = Server.HtmlEncode(name);
         return Content(input);
      }
   }
}

When you request the following URL http://localhost:61465/Employee/Mark, then you will receive the following output as an action.

Localhost Employee Mark Output

Add Controller

Let us add one another controller.

Step 1 − Right-click on Controllers folder and select Add → Controller.

Add Another Controller

It will display the Add Scaffold dialog.

Add Scaffolding Dialog

Step 2 − Select the MVC 5 Controller – Empty option and click ‘Add’ button.

The Add Controller dialog will appear.

CustomerController

Step 3 − Set the name to CustomerController and click ‘Add’ button.

Now you will see a new C# file ‘CustomerController.cs’ in the Controllers folder, which is open for editing in Visual Studio as well.

set_name CustomerController

Similarly, add one more controller with name HomeController. Following is the HomeController.cs class implementation.

using System;
using System.Collections.Generic;
using System.Linq;

using System.Web;
using System.Web.Mvc;

namespace MVCControllerDemo.Controllers {
   public class HomeController : Controller{
      // GET: Home
      public string Index(){
         return "This is Home Controller";
      }
   }
}

Step 4 − Run this application and you will receive the following output.

Home Controller Output

Step 5 − Add the following code in Customer controller, which we have created above.

public string GetAllCustomers(){
   return @"<ul>
      <li>Ali Raza</li>
      <li>Mark Upston</li>
      <li>Allan Bommer</li>
      <li>Greg Jerry</li>
   </ul>";
}

Step 6 − Run this application and request for http://localhost:61465/Customer/GetAllCustomers. You will see the following output.

Localhost GetAllCustomers

You can also redirect to actions for the same controller or even for a different controller.

Following is a simple example in which we will redirect from HomeController to Customer Controller by changing the code in HomeController using the following code.

using System;
using System.Collections.Generic;
using System.Linq;

using System.Web;
using System.Web.Mvc;

namespace MVCControllerDemo.Controllers{
   public class HomeController : Controller{
      // GET: Home
      public ActionResult Index(){
         return RedirectToAction("GetAllCustomers","Customer");
      }
   }
}

As you can see, we have used the RedirectToAction() method ActionResult, which takes two parameters, action name and controller name.

When you run this application, you will see the default route will redirect it to /Customer/GetAllCustomers

Localhost Customers GetAllCustomers

 

References

tutorialspoint
posted Jul 2, 2017 by Shivaranjini

  Promote This Article
Facebook Share Button Twitter Share Button LinkedIn Share Button


Related Articles

Method overloading is very common technique used in C# code. Although it works great for normal C# classes, the same can't be said about ASP.NET MVC controller classes. If you ever tried to implement method overloading for MVC actions you are probably aware of the following exception:

image

Unlike an ordinary C# class, a controller is dealing with HTTP protocol. And HTTP doesn't understand overloading as C# does. So, in case you wish to use method overloading in a controller you need to consider the four possible ways as discussed in the remainder of this article.

Actions handling different HTTP verbs

In this scenario you have two action methods with the same name BUT they handle different HTTP verbs. Consider the following fragment of code:

public ActionResult Index()
{
    return View();
}

[HttpPost]
public ActionResult Index(Customer obj)
{
    //do something with obj
    return View();
}

As you can see the first Index() action deals with the GET requests whereas the second Index() action deals with POST requests. The first version is parameter-less whereas the second accepts a parameter of type Customer (this depends on what you are submitting from the view. The above example assumes you are submitting customer data).

The above overloaded methods work fine since each is dealing with different HTTP verb.

Actions handling GET requests and attribute routing

You can overload actions dealing with GET requests if you configure attribute routing properly. The following example will make this clear:

[Route("Home/DoWork/{status:int}")]
public ActionResult DoWork(int status)
{
    return View();
}

[Route("Home/DoWork/{flag:bool}")]
public ActionResult DoWork(bool flag)
{
    return View();
}

Now in this case there are two DoWork() actions but one has an integer parameter whereas the other has a boolean parameter. Moreover, [Route] attribute is used to configure attribute based routing. Notice that the first [Route] attribute specifies that status parameter is int and the second specifies that it is bool. So, if a URL is /home/dowork/10 then it will be handled by the first DoWork() whereas if the URL is /home/dowork/true it will be handled by the second DoWork() action.

Make sure you call MapMvcAttributeRoutes() in the RouteConfig.cs file before you test this technique.

Overloaded actions marked as [NonAction]

In this technique you create a public action method as usual. And then create several overloads of it as that are not MVC actions. These overloads are marked as [NonAction] attribute. The following code fragment will make it clear:

[HttpPost]
public ActionResult Calculate()
{
    int i = int.Parse(Request.Form["num1"]);
    int j = int.Parse(Request.Form["num2"]);
    return Calculate(i , j);
}

[NonAction]
public ActionResult Calculate(int i, int j)
{
    return View( i + j );
}

Here, the first method - Calculate() - acts as an MCV action method. The Calculate() then invokes an overload - Calculate(int,int). The overload does its job and returns a view to the caller. Notice that the second Calculate() is marked with [NonAction] attribute. The [NonAction] attribute indicates that the method under consideration should not be treated as an action. Since the method is no longer an action it doesn't interfere in the working of HTTP and the controller.

[ActionName] attribute

 In this technique you create overloaded action methods as you would have done in any C# class. But give them another unique name using the [ActionName] attribute. The following code fragment will make it clear:

[HttpPost]
[ActionName("ProcessForm1")]
public ActionResult ProcessForm(Customer obj)
{
    return View();
}

[HttpPost]
[ActionName("ProcessForm2")]
public ActionResult ProcessForm(Employee emp)
{
    return View();
}

Here, we have two overloads of the ProcessForm() actions. However, both have [ActionName] attribute added on top of them. The [ActionName] attribute assigns a unique name to a method that is then used by the MVC framework. That means for your C# code the method name remains ProcessForm() but for the MVC framework (including routing engine and HTML helpers) they represent two methods - ProcessForm1() and ProcessForm2().

Remember that when you use [ActionName] attribute you are assigning a different name to the action method under consideration. In helpers such as BeginForm() and ActionLink() you should use the name as defined in the [ActionName] attribute (ProcessForm1 and ProcessForm2 in this case).

That's it! Although it is better to keep away from method overloading in the controllers, if at all you wish to implement overloading you can use one of the above ways. As you can see using overloading adds a bit of complexity to your controller.  But it is possible in a limited way if needed.

READ MORE

Routing is the process of directing an HTTP request to a controller and the functionality of this processing is implemented in System.Web.Routing. This assembly is not part of ASP.NET MVC. It is actually part of the ASP.NET runtime, and it was officially released with the ASP.NET as a .NET 3.5 SP1.

System.Web.Routing is used by the MVC framework, but it's also used by ASP.NET Dynamic Data. The MVC framework leverages routing to direct a request to a controller. The Global.asax file is that part of your application, where you will define the route for your application.

This is the code from the application start event in Global.asax from the MVC App which we created in the previous chapter.

using System;
using System.Collections.Generic;
using System.Linq;

using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace MVCFirstApp {
   public class MvcApplication : System.Web.HttpApplication {
      protected void Application_Start(){
         AreaRegistration.RegisterAllAreas();
         RouteConfig.RegisterRoutes(RouteTable.Routes);
      }
   }
}

Following is the implementation of RouteConfig class, which contains one method RegisterRoutes.

using System;
using System.Collections.Generic;
using System.Linq;

using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace MVCFirstApp {
   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});
      }
   }
}

You will define the routes and those routes will map URLs to a specific controller action. An action is just a method on the controller. It can also pick parameters out of that URL and pass them as parameters into the method.

So this route that is defined in the application is the default route. As seen in the above code, when you see a URL arrive in the form of (something)/(something)/(something), then the first piece is the controller name, second piece is the action name, and the third piece is an ID parameter.

Understanding Routes

MVC applications use the ASP.NET routing system, which decides how URLs map to controllers and actions.

When Visual Studio creates the MVC project, it adds some default routes to get us started. When you run your application, you will see that Visual Studio has directed the browser to port 63664. You will almost certainly see a different port number in the URL that your browser requests because Visual Studio allocates a random port when the project is created.

Localhost Home

In the last example, we have added a HomeController, so you can also request any of the following URLs, and they will be directed to the Index action on the HomeController.

http://localhost:63664/Home/

http://localhost:63664/Home/Index

When a browser requests http://mysite/ or http://mysite/Home, it gets back the output from HomeController’s Index method.

You can try this as well by changing the URL in the browser. In this example, it is http://localhost:63664/, except that the port might be different.

If you append /Home or /Home/Index to the URL and press ‘Enter’ button, you will see the same result from the MVC application.

Localhost Home Index

As you can see in this case, the convention is that we have a controller called HomeController and this HomeController will be the starting point for our MVC application.

The default routes that Visual Studio creates for a new project assumes that you will follow this convention. But if you want to follow your own convention then you would need to modify the routes.

Custom Convention

You can certainly add your own routes. If you don't like these action names, if you have different ID parameters or if you just in general have a different URL structure for your site, then you can add your own route entries.

Let’s take a look at a simple example. Consider we have a page that contains the list of processes. Following is the code, which will route to the process page.

routes.MapRoute(
   "Process",
   "Process/{action}/{id}",
   defaults: new{
      controller = "Process", action = "List ", id = UrlParameter.Optional}
);

When someone comes in and looks for a URL with Process/Action/Id, they will go to the Process Controller. We can make the action a little bit different, the default action, we can make that a List instead of Index.

Now a request that arrives looks like localhosts/process. The routing engine will use this routing configuration to pass that along, so it's going to use a default action of List.

Following is the complete class implementation.

using System;
using System.Collections.Generic;
using System.Linq;

using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

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

Step 1 − Run this and request for a process page with the following URL http://localhost:63664/Process

Localhost Process

You will see an HTTP 404, because the routing engine is looking for ProcessController, which is not available.

Step 2 − Create ProcessController by right-clicking on Controllers folder in the solution explorer and select Add → Controller.

Create ProcessController

It will display the Add Scaffold dialog.

ProcessController Scaffolding Dialog

Step 3 − Select the MVC 5 Controller – Empty option and click ‘Add’ button.

The Add Controller dialog will appear.

Empty Option Add Button

Step 4 − Set the name to ProcessController and click ‘Add’ button.

Now you will see a new C# file ProcessController.cs in the Controllers folder, which is open for editing in Visual Studio as well.

Set ProcessControllerNow our default action is going to be List, so we want to have a List action here instead of Index.

Step 5 − Change the return type from ActionResult to string and also return some string from this action method using the following code.

using System;
using System.Collections.Generic;
using System.Linq;

using System.Web;
using System.Web.Mvc;

namespace MVCFirstApp.Controllers{
   public class ProcessController : Controller{
      // GET: Process
      public string List(){
         return "This is Process page";
      }
   }
}

Step 6 − When you run this application, again you will see the result from the default route. When you specify the following URL, http://localhost:63664/Process/List, then you will see the result from the ProcessController.

Localhost Process List

 

READ MORE
...