In the last article we went through the basics of MVC. In this article we will see details of how the controller works. Whenever a new request comes into an ASP.NET MVC application it is handled by the controller class. It decides how to handle the request. Normally it fetches (or updates) the data from the model and renders the appropriate view to display the results. Let's see how the controller processes the request and produces the appropriate output. As we already know, controllers are in charge of the application logic. The application logic requires obtaining inputs from the user (or responding to other user actions) and fetching the data from the model for the user, which is displayed by the view.
Controllers in ASP.NET are classes implementing the IController interface. Most of the time we will not be interacting with this interface but rather deriving from the System.Web.Mvc. Controller which implements the IController Interface for us and also provides additional functionality. The action methods in the controller are provided by this base Controller class.
The following method is an action method:
The action method always returns an ActionResult type or type derived from this type. Also note that any public nonstatic method in the controller is an action method and can be invoked by the user using a URL. Also the URLs for each action method is different.
The above is just a default action method. Let us create a more useful action.
public ActionResult Index ()
{
string userIP = Request.UserHostAddress;
bool isSecure = Request.IsSecureConnection;
ViewData["userIP"]=userIP;
ViewData["isSecure"] = isSecure;
return View();
}
This action directly retrieves the values from the context objects.
Other properties we will be commonly using are:
Request.QueryString - For retrieving GET variables sent with this request
Request.Form - For retrieving POST variables sent with this request
Request.UserHostAddress - The IP address of the user making thisRequest
HttpContext.Cache - For storing cache information
HttpContext.Session - For storing session information
Though we are always free to directly retrieve the input values from the context objects, doing so is against the separation of concerns principle supported by MVC applications. So usually we will use the action method parameters to retrieve the input values.
So instead of this code:
public ActionResult Info()
{
string strName = (string) Request.Form["UserName"];
We should be using this:
public ActionResult Info(string UserName)
{
If we use parameters then insensitive case name matching is used. So in the above code the parameter UserName would be populated from both.
Request.Form["UserName"] (Camel case) and Request.Form["username"] (Small case)
If we don't supply any parameter value it will be null for reference types but for value types if we don't supply a parameter value then an error will be thrown. To prevent this, we optionally can use parameters to supply default parameter values for the value types, as in:
public ActionResult Info(string UserName,int id = 001)
{
Once the controller has received and processed the input, it can react in various ways by:
- Directly writing the output to the output stream
- Rendering HTML using a view
- Redirecting to another action method
Directly writing output to output stream
To directly write the output we can use the familiar Response.Write () as:
public void Index()
{
Response.Write("Hello from MVC action method");
}
Using ActionResult
Instead of directly writing the Respnse from the action method (which is against the separation of concerns supported by MVC) we usually return the ActionResult type from the action method which generates the appropriate response for us.
Notice that return View() generates the ViewResult which is derived from ActionResult. ViewResult renders the named view or default view (if none is specified).
Other commonly used ActionResult types are:
PartialViewResult - Renders partial views
RedirectToAction - For redirecting to another action method
FileResult - For writing binary file data
ContentResult - For writing textual data
Please note that executing View() without any parameters calls the default view of the action. If we want, we can call any other view using the following:
return View("VewName");
As we saw in the last article, we can pass data to the view using the ViewData dictionary as:
ViewData["Key1"] = "value1";
Which we can access in the view as:
<%: ViewData["Key1"] %>
Besides this approach we can pass the data to the view using the Model property of the ViewData object. For example the following code sets the Model property to the product object.
Product product=new Product();
product.Name = "Smart Cell Phone";
ViewData.Model = product;
Now we can access it in the view as:
The Product is <%: ((Model.Entities.Product)Model).Name%>
The above code still uses the type casting to convert the Model object to the appropriate type. We can avoid this type casting by using the strongly typed views. When we create a new view we can create the strongly typed view. We just need to select the ViewData class.
We select the Product class for the Views Data Class:
Now we can directly access the Product object in the view without type casting as:
The Product is <%: Model.Name%>
Redirecting to a different Action method
We can redirect to another action method using the RedirectToAction method (which is of the ResultAction type).
To redirect to another action method we can use the code as:
public ViewResult Info()
{
//the following view displays the information about the saved data
return View();
}
public ActionResult Save()
{
//the following method saves the data
//logic to save the data
return RedirectToAction("Info");
}
The Save () method above could save the data in the database while the Info () method displays the result once the data is saved so that different methods could handle different tasks properly.