Thứ Tư, 27 tháng 8, 2014

Using the Grid.MVC in ASP.NET MVC

Introduction 

Most of times we will have to show data in our apps, but we need to provide different features like paging, filtering, sorting and much more, so the Grid.MVC provides amazing tools for that goal when we develop applications using ASP.NET MVC.

Background

This article shows how through the Grid.MVC you can use features like paging, filtering and sorting.

Using the code   

Firts step: create a new ASP.NET MVC 4 application, I recommended to use the basic template.

Next, lets create a new class Client, this class will be the model:
public class Client
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Email { get; set; }
}
Now that you have the model done, lets create the Client controller. This controller have only on action, and the data source will be a List, but here you can connect to a database, the action returns the data:
public class ClientController : Controller
{
    private readonly List clients = new List()
    {
        new Client { Id = 1, Name = "Julio Avellaneda", Email = "julito_gtu@hotmail.com" },
        new Client { Id = 2, Name = "Juan Torres", Email = "jtorres@hotmail.com" },
        new Client { Id = 3, Name = "Oscar Camacho", Email = "oscar@hotmail.com" },
        new Client { Id = 4, Name = "Gina Urrego", Email = "ginna@hotmail.com" },
        new Client { Id = 5, Name = "Nathalia Ramirez", Email = "natha@hotmail.com" },
        new Client { Id = 6, Name = "Raul Rodriguez", Email = "rodriguez.raul@hotmail.com" },
        new Client { Id = 7, Name = "Johana Espitia", Email = "johana_espitia@hotmail.com" }
    };
 
    public ActionResult Index()
    {
        return View(clients);
    }
} 

Before create the view, will need to add a Grid.MVC package using Nuget:
 
Also add Boostrap:


When the Grid.MVC package is installed, you can found some new views in the Views/Shared folder:

In the scripts folder, tree new JavaScript files will be found:
 
And in the content folder now you see the css file for the Grid:

Next step now is to create a new View for the action Index of the controller Client, like this:
@model IEnumerable<Grid.Models.Client>
@using GridMvc.Html
 
@{
    Layout = null;
}
 
<!DOCTYPE html>
 
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <link href="@Url.Content("~/Content/Gridmvc.css")" rel="stylesheet" />
    <link href="@Url.Content("~/Content/bootstrap.min.css")" rel="stylesheet" />
    <script src="@Url.Content("~/Scripts/jquery-1.9.1.min.js")"></script>
    <script src="@Url.Content("~/Scripts/gridmvc.min.js")"></script>
    <title>Index</title>
</head>
<body>
    <h1>Grid.MVC</h1>
    <hr />
    <div style="width:500px;">
        @Html.Grid(Model).Columns(columns => 
                    {
                        columns.Add(c => c.Id).Titled("Client ID");
                        columns.Add(c => c.Name).Titled("Name").Filterable(true);
                        columns.Add(c => c.Email).Titled("Email");
                    }).WithPaging(3).Sortable(true)
    </div>
</body>
</html>
The key parts on the code are:
  • Add: @using GridMvc.Html 
  • Add the references to the css files
  • Add the references to the JavaScript files
To use the Grid, use the HTML Helper @Html.Grid, some important properties for the helper:
  • Titled: The column title
  • Filterable: Define if the column has the feature to be filterable
  • Sortable: Define if the column has the feature to be sortable
  • WithPaging: Define the number of rows to show for page 
Finally, you have the following cool Grid:




I hope this post will be useful for you!

Using TempData Outside the Controller in ASP.NET MVC


2 Jun 2014
Using TempData outside the controller in ASP.NET MVC and making TempData less prone to error and more intuitive.
Is your email address OK? You are signed up for our newsletters but your email address is either unconfirmed, or has not been reconfirmed in a long time. Please click here to have a confirmation email sent so we can confirm your email address and start sending you newsletters again. Alternatively, you can update your subscriptions.

What is the Problem We Are Trying to Fix?

When you start using Tempdata, it quickly becomes evident that maintaining it will be quite a challenge because Intellisense doesn't support Tempdata since it's a Dictionary. Without intellisense, suddenly life looks gloomy, but no fear. There is hope!

My Problem

The problem raised when I wanted to use Notification Object across my website. I wanted to throw this object from one controller to the other (tempdata job) and finally send it to the view. If I wanted to useTempData["something"], then I have to remember this "something".
So instead of hardcoding this "something" inside the controller, I decided to put the hardcoding inside aHelper.cs function and simply call intuitive functions that will Get/Set/Remove the object. The beauty of it is that - there is Intellisense to help us out!

Solution

The solution is quite simple.
  1. Create the Notification object
  2. Create a helper function that will do the dirty work (get;set;remove)
Since we moved TempData outside the controller, we are obliged to send the controller to be able to use theTempData. We send the controller by the keyword this.

PromptNotification.cs

public class PromptNotification //Notification Object
{
    public bool NotificationSuccess { get; set; }
    public string NotificationMessage { get; set; }
}

Helper.cs

public static void SetPromptNotification(Controller controller, bool success,string message)
{
    PromptNotification promptNotification = new PromptNotification
    {
        NotificationSuccess = success,
        NotificationMessage = message
    };
    controller.TempData["PromptNotification"] = promptNotification;
}

public static PromptNotification GetPromptNotification(Controller controller)
{
    try
    {
        PromptNotification promptNotification = controller.TempData["PromptNotification"] 
            as PromptNotification;
        return promptNotification;
     }
     catch (Exception ex)
     {
         // log error here

         return null;
     }
}

public static void RemovePromptNotification(Controller controller)
{
    controller.TempData.Remove("PromptNotification");
}

UserController.cs //set

// add promp message => redirect to index
Helper.SetPromptNotification(this, true, 
    "You will shortly receive an email, please verify your registration.");

MainController.cs //get

// get promptnotification => if it exist => pass it to the view => clear the notification
PromptNotification promptNotification = Helper.GetPromptNotification(this);

if (promptNotification != null)
{
    ViewBag.NotificationSuccess = promptNotification.NotificationSuccess;
    ViewBag.NotificationMessage = promptNotification.NotificationMessage;

    Helper.RemovePromptNotification(this);
}

Index.cshtml

@if (ViewBag.NotificationSuccess != null)
{
    PromptNotification promptNotification = new PromptNotification
    {
        NotificationSuccess = (bool)ViewBag.NotificationSuccess,
        NotificationMessage = ViewBag.NotificationMessage as string
    };
    
    string notificationClassName = String.Empty;

    if (promptNotification.NotificationSuccess == true)
    {
        notificationClassName = "notificationSuccessWrapper";
    }
    else
    {
        notificationClassName = "notificationErrorWrapper";
    }
    
    <div class="@Html.Raw(notificationClassName)">
        @promptNotification.NotificationMessage
    </div>
}

Using TempData in ASP.NET MVC

In previous ASP.NET MVC Tutorial, we discussed about different available options for passing data from Controller to View in ASP.NET MVC. We implemented passing data using ViewBag and ViewData in ASP.NETMVC application. Now, in this part of the tutorial, we are going to discuss about the third available option i.e.TempData.
TempData in ASP.NET MVC is basically a dictionary object derived from TempDataDictionaryTempDatastays for a subsequent HTTP Request as opposed to other options (ViewBag and ViewData) those stay only for current request. So, TempdData can be used to maintain data between controller actions as well as redirects.
Note: Just like ViewData, typecasting and null checks required for TempData also in order to avoid errors.
Let’s see how we can use TempData in a practical scenario to pass data from one controller action to another.
   //Controller Action 1 (TemporaryEmployee)
   public ActionResult TemporaryEmployee()
  {
                  Employee employee = new Employee
                  {
                          EmpID = "121",
                          EmpFirstName = "Imran",
                          EmpLastName = "Ghani"
                  };                   
                  TempData["Employee"] = employee;
                  return RedirectToAction("PermanentEmployee");
  }   
 
   //Controller Action 2(PermanentEmployee)
   public ActionResult PermanentEmployee()
  {
                 Employee employee = TempData["Employee"] as Employee;
                 return View(employee);
   }
As in above example, we store an employee object in TempData in Controller Action 1 (i.e.TemporaryEmployee) and retrieve it in another Controller Action 2 (i.e. PermanentEmployee). But If we try to do the same using ViewBag or ViewData, we will get null in Controller Action 2 because only TempDataobject maintains data between controller actions.
An important thing about TempData is that it stores contents in Session object. Then one may raise a question that “What’s the difference between TempData in ASP.NET MVC and Session?” or “Why we have TempData dictionary object?, Why can’t we use the Session object directly?

ASP.NET MVC TempData Vs Sessions

Although ASP.NET MVC TempData stores it’s content in Session state but it gets destroyed earlier than a session object. TempData gets destroyed immediately after it’s used in subsequent HTTP request, so no explicit action required. If we use a Session object for this purpose, we would have to destroy the object explicitly.
It’s best fit for scenarios when:
  • we need to preserve data from current to subsequent request.
  • passing error message to an error page.
With the above discussion on using TempData in ASP.NET MVC, we have successfully covered different options for passing data from Controller to View in ASP.NET MVC. Hopefully reader will have a better understanding of using ViewBag, ViewData and TempData in ASP.NET MVC.

Routing in MVC

This article explains routing in MVC. How a route is executed by the routing engine and how to define a route for a URL.

Introduction

This article explains routing in MVC. How a route is executed by the routing engine and how to define a route for a URL.
ASP.NET MVC routing is a pattern matching system that is responsible for mapping incoming browser requests to specified MVC controller actions. When the ASP.NET MVC application launches then the application registers one or more patterns with the framework's route table to tell the routing engine what to do with any requests that matches those patterns. When the routing engine receives a request at runtime, it matches that request's URL against the URL patterns registered with it and gives the response according to a pattern match. Let's see Figure 1.1.
ASP.NET MVC Routing
Figure 1.1 ASP.NET MVC Routing
In Figure 1.1 we can see how the routing engine processes a request and what response it sends. It gives a response according to URL match or not in the route table.
  1. When the request's URL matches any of the registered route patterns in the route table then the routing engine forwards the request to the appropriate handler for that request. Thereafter the route is processed and gets a view on the UI.
  2. When the request's URL does not match any of the registered route patterns then the routing engine indicates that it could not determine how to handle the request by returning a 404 HTTP status code.

Properties of Route

ASP.NET MVC routes are responsible for determining which controller method to execute for a given URL. A URL consists of the following properties:
  • Route Name:A route is a URL pattern that is mapped to a handler. A handler can be a controller in theMVC application that processes the request. A route name may be used as a specific reference to a given route.
  • URL Pattern: A URL pattern can contain literal values and variable placeholders (referred to as URL parameters). The literals and placeholders are located in segments of the URL that are delimited by the slash (/) character.
  • When a request is made, the URL is parsed into segments and placeholders, and the variable values are provided to the request handler. This process is similar to the way the data in query strings is parsed and passed to the request handler. In both cases variable information is included in the URL and passed to the handler in the form of key-value pairs. For query strings both the keys and the values are in the URL. For routes, the keys are the placeholder names defined in the URL pattern, and only the values are in the URL.
  • Defaults:When you define a route, you can assign a default value for a parameter. The defaults is an object that contains default route values.
  • Constraints: A set of constraints to apply against the URL pattern to more narrowly define the URL that it matches.

Understand the Default Route

The default ASP.NET MVC project templates add a generic route that uses the following URL convention to break the URL for a given request into three named segments.
url: "{controller}/{action}/{id}"
This route pattern is registered via call to the MapRoute() extension method of RouteCollection.
Default Routes for MVC Application
Figure 1.2 Default Routes for MVC Application
When the MVC application launches the Application_Start() event handler of the global.asax execute that call the RegisterRoutes() method from RouteConfig class under App_Start directory (App_Start/RouteConfig.cs). The RegisterRoutes() route has a parameter that is a collection of routes called the RouteCollection that contains all the registered routes in the application. The Figure 1.2 represents the default method that adds routes to the route table.

Routing with an Example

When the application starts up, ASP.NET MVC discovers all of the application's controllers by searching through the available assemblies for a class that implements the System.Web.Mvc. The IControllerinterface or derived from a class that implements this interface and whose class names end with the suffix Controller. When the routing framework uses this list to determine which controller it has access to, it chops off the Controller suffix from the entire controller class names.
In the previous article CRUD Operations Using the Repository Pattern in MVC I implemented Create, Read, Update, and Delete operations on a book entity. So we will use this example to understand URL routing. Our default route is the same as in Figure 1.2 for CRUD applications also.
URLControllerActionId
http://localhost:4736/HomeControllerIndex 
http://localhost:4736/Book/BookControllerIndex 
http://localhost:4736/Book/CreateBookControllerCreate 
http://localhost:4736/Book/Edit/2BookControllerEdit2
Table 1.1 Request's URLs that match our default route pattern
The last request's URL (http://localhost:4736/Book/Edit/2) in the table 1.1 is a perfect match to the registered default URL pattern because it satisfies every segment of the route pattern, but when we don't provide a complete request's URL then the routing engine automatically calls the controller and action method as per the default route pattern.

Conclusion

The controller and action values in the route are not case-sensitive. URL route patterns are relative to the application root, so they don't need to start with a forward slash (/) or virtual path designator (~/).

Actions in ASP.NET MVC 3

Introduction

ASP.NET MVC provides a new way of creating web applications which are more extensible and testable. We discussed about ASP.NET MVC in Introduction to ASP.NET MVC 3. Also, we discussed about Routers and Controllers in ASP.NETMVC 3. Here, we will take a deeper look into the different Actions, Action filters, and selectors used inside a Controller.

Action Result

By default, the Controller actions will return the ActionResult object. We can return various types of results asActionResult, which will decide how the output needs to render on the browser.
public ActionResult About()
{
    return View();
}

Sample Controller

For our sample, we will use the following SampleController in addition to the default HomeController andAccountController.
public class SampleController : Controller
{
    //
    // GET: /Sample/

    public ActionResult Index()
    {
        return Content("Hello from Index action in Sample Controller");
    }
    public ActionResult Verify(string username = "all")
    {
        return Content("Hello from Verify action in Sample Controller");
    }

}
Here, we will discuss about some of the ActionResults available as part of ASP.NET MVC 3.

1. Content

When we need to return any text from a Controller action, we will use the Content type.
public ActionResult Index()
{
    return Content("Hello from Home Controller");
}

2. RedirectToAction

Depending on the input values, we can redirect to another Action. For redirecting to another Action, we will use theRedirectToAction type.
public ActionResult Index()
{
    // Redirect to Verify action inside the Sample Controller
    return RedirectToAction("Verify", "Sample");
}

3. RedirectToRoute

When we need to redirect to a route defined in Global.asax, we will use the RedirectToRoute object.
As part of our sample application, we have a custom route defined with the name “sample”. This will route to the Index action inside the Sample Controller. For more on Custom routes, please refer to Controllers and Routers in ASP.NETMVC 3.
public ActionResult Index()
{
    return RedirectToRoute("sample");
}

4. File

File is used to return the content of a file to the browser. For our sample, I am returning the web.config to the browser.
public ActionResult Index()
{
    return File("Web.config", "text/html");
}

5. JSON

We can render the text to the result page or can send it as a file to the client using JSON notation.
public ActionResult Index()
{
    return Json("hello from JSON","text/html", JsonRequestBehavior.AllowGet);
}
As we specified the type of the content, it will render to the browser as shown below:
public ActionResult Index()
{
    return Json("hello from JSON", JsonRequestBehavior.AllowGet);
}
If there is no content type specified, it will download the content as a file.

Action Filters

There are a set of Action filters available with ASP.NET MVC 3 to filter actions. Action filters are defined as attributes and applied to an Action or controller.

1. Authorize

Authorize filters ensure that the corresponding Action will be called by an authorized user only. If the user is not authorized, he will be redirected to the login page.
[Authorize]
public ActionResult About()
{
    return View();
}
If the user is not authorized and invoke the About action, then he will redirected to the log on page.
If we need the filter at the controller level, then we can add the filter to the controller class itself.
[Authorize]
public class SampleController : Controller
{
    ……………………………………………
}

2. HandleError

HandleError will handle the various exceptions thrown by the application and display user friendly message to the user. By default, this filter is registered in Global.asax.
Note: If any of the Action filters are added to the filter collection in Global.asax, then the scope of the filter is the application.
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    filters.Add(new HandleErrorAttribute());
}
For verifying a filter, let us enable a custom error in web.config:
<customErrors mode="On"/>
Now throw an exception from the Home Controller:
public ActionResult Index()
{
    throw new Exception("Verify the HandleError filter");
    ViewBag.Message = "Welcome to ASP.NET MVC!";
    return View();
}
Now run the application and observe the custom error message:
This View is defined under Shared Views. We can change the error message using the Error.cshtml file.
Now, let us remove the filter from Global.asax and verify our application. We will receive the following server error:
Now, let us update the CustomError tag to RemoteOnly and verify our application. Now we can see this error message thrown by the application:
We can specify the HandleError filter for an Action or a controller.
ASP.NET MVC defines Action filters like OutputCacheValidateInput, etc., as part of ASP.NET MVC 3, which we will discuss later.

Action Selectors

ASP.NET MVC 3 defines a set of Action selectors which determine the selection of an Action. One of them isActionName, used for defining an alias for an Action. When we define an alias for an Action, the Action will be invoked using only the alias; not with the Action name.
[ActionName("NewAbout")]
public ActionResult About()
{
    return Content("Hello from New About");
}
ASP.NET has more Action selectors like HTTPPost and HTTPGet, which we will discuss later.

Conclusion

Here we had a quick discussion of the various Action result options and Action filters. We will discuss more about Views, Styles, etc., in the next article.