Free Online Courses for Software Developers - MrBool
× Please, log in to give us a feedback. Click here to login
×

You must be logged to download. Click here to login

×

MrBool is totally free and you can help us to help the Developers Community around the world

Yes, I'd like to help the MrBool and the Developers Community before download

No, I'd like to download without make the donation

×

MrBool is totally free and you can help us to help the Developers Community around the world

Yes, I'd like to help the MrBool and the Developers Community before download

No, I'd like to download without make the donation

All in One - Actions in MVC3

I am talking about the ability to write an action that can serve both Ajax requests and non-Ajax request. Instead of writing many actions for each type of the request, you can use the following technic, the AllInOneAction as I call it

Introduction

I am talking about the ability to write an action that can serve both Ajax requests and non-Ajax request. Instead of writing many actions for each type of the request, you can use the following technic, the AllInOneAction as I call it.

In today’s lesson, we are going to see how an action can:

  • Return a partial view if the request is simply an Ajax request;
  • Return a jSon object view if the request is an Ajax requestthat expects a json result (for a mobile user interface for example);
  • Return a View in other cases.

In addition, we will learn:

  • A pagination technic.
  • How to handle errors and exceptions as well.

Pre-requisites

To follow this lesson you must be good with:

  • Basics in Asp.net mvc 3
  • Visual studio 2010

Let’s go to the example!

Step1. Create a new Project

img1

Step2. Add a controller named: ‘AllInOneController’

img2

Step3. Add this class in the ModelDirectory

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

namespace AllInOneActions.Models
{
	public class StudentModel
	{
		public long studentId{ get; private set;}
		public string FirstName {get; set;}
		public string LastName {get; set;}
		public DateTime BirthDay {get; set;}
		

		public StudentModel(){}
	
		public StudentModel(long sId){
			this.studentId=sId;
		}

public static List<StudentModel> LoadStudents(){
	
	List<StudentModel> students = new List<Models.StudentModel>();
	StudentModel student;
	for(long i = 1; i <= 10; i++){

	student = new StudentModel(i);
	student.FirstName = "FName"+i.ToString();
	student.LastName = "LName" + i.ToString();
	student.BirthDay = DateTime.Now.AddYears(-20);
	student.Add(student);
	}
	return students;
} 
 

Note: to stay simple, we use this class instead of using a database. But it in your case, you can use any model class, even an entity framework. Given you pay attention to avoid circular reference (to avoid the circular reference, please see the solution below).

Step4. Let’s go back into our AllInOneController, take the Index action. Think this action is destined to return a paginated list of students. Here is the way I code:

// GET: /AllInOne/ 
publicActionResult Index(int? i, int? n)
{
	try{
			var Students = AllInOneActions.Models.StudentModel.LoadStudents()
											.Skip(i   0)
											.Take(n   4);
			 
			if (Request.IsAjaxRequest()){
					if (Request.Params["json"] != null){
							int page = i   0;
							int count = n   4;
							
							varjSonObject = new{
								paginationIndex = page,
								count = count,
								error=false,
								datas = Students
							};
						returnJson(jSonObject,"text/json",JsonRequestBehavior.AllowGet);
					}
				returnPartialView("IndexPartial", Students.ToList());
			}
		return View(Students.ToList());
		
		}catch (Exception ex){
			string message = "Sorry! an exception occured : " + ex.Message;
			 
			if (Request.IsAjaxRequest()){
			if (Request.Params["json"] != null){
			varjSonObject = new{
			error = true,
			Message = message
									};
			returnJson(jSonObject);
								}
			ViewBag.Message = message;
			returnPartialView("NoticePartial");
							}
			ViewBag.Message = message;
			return View("NoticePartial");

		}
}

Explanation:

        publicActionResultIndex(int? i, int? n){
The index action has two params that can be NULL that’s why I’ve written int? i instead of int i. Further in this code, you can find this notation
var Students = AllInOneActions.Models.StudentModel.LoadStudents()
     .Skip(i   0)
     .Take(n   4);

In this code, the LoadStudents returns a list of students. This list can have many items, for example 200000 students. This can of request will take too much time. That’s why I take a limit of n items. In case n has no value, the value 4 will be used. So, in dotnet, you can write x 20 to mean that, if the nullable variable x doesn’t have a value, use 20 instead.

The Skip() method allows us to start by a given value, instea of starting by the first element of the list.

Request.IsAjaxRequest() Method

This method returns true if the request is an action request and false otherwise. To test if the Ajax request is expecting a json result or not, we are going to add a parameter in our request. The following lines of codes will test if the Ajax request has a parameter named json or not. If the request expects the result to be json formatted, we will return a json string with pagination information. Read the code to understand well.

if (Request.Params["json"] != null){
	int page = i   0;
	int count = n   4;
		varjSonObject = new{
			paginationIndex = page,
			count = count,
			error=false,
			datas = Students
		};
	returnJson(jSonObject,"text/json",JsonRequestBehavior.AllowGet);
}

 

Here is the partial view code (IndexPartial.ascx)

<%@ControlLanguage="C#"Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<AllInOneActions.Models.StudentModel>>"%>
  
<table>
	<tr>
		<th>studentId</th>
		<th>FirstName</th>
		<th>LastName</th>
		<th>BirthDay</th>
		<th></th>
	</tr>
	  
	<% foreach (var item in Model) { %>
	 
	<tr>
		<td><%:Html.DisplayFor(modelItem =>item.studentId) %></td>
		<td><%:Html.DisplayFor(modelItem =>item.FirstName) %></td>
		<td><%:Html.DisplayFor(modelItem =>item.LastName) %></td>
		<td><%:Html.DisplayFor(modelItem =>item.BirthDay) %></td>
		<td>
			<%:Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) %> |
			<%:Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) %> |
			<%:Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ }) %>
		</td>
	</tr>
<%	} %> 
</table>
 
<%
try{
    intinfLimit = (Request.Params["i"] != null) ? int.Parse(Request.Params["i"]) : 0;
    intitemsCount = (Request.Params["n"] != null) ? int.Parse(Request.Params["n"]) : 4;
%>
  
<%:Html.ActionLink("Prev", "Index", new {i=infLimit-itemsCount>0?infLimit-itemsCount:0, n=itemsCount }) %>
<%:Html.ActionLink("Next", "Index", new {i=infLimit+itemsCount, n=itemsCount }) %>
<%
   }catch (Exception){ 
     
   } 
%>

And The Index View will call this partial view as follow

<%@PageTitle=""Language="C#"MasterPageFile="~/Views/Shared/Site.Master"Inherits="System.Web.Mvc.ViewPage<IEnumerable<AllInOneActions.Models.StudentModel>>"%>

<asp:ContentID="Content1"ContentPlaceHolderID="TitleContent"runat="server">
    Index
</asp:Content>

<asp:ContentID="Content2"ContentPlaceHolderID="MainContent"runat="server">

<h2>Index</h2>
<%Html.RenderPartial("IndexPartial", Model); %>
</asp:Content>

Handling errors and exceptions

To handle errors properly, I put each code in a try catch statement. In addition, I created a notice view that will show the error message stored in the ViewBag. Here is a part of the code


catch (Exception ex){
		string message = "Sorry! an exception occured : " + ex.Message;
			if (Request.IsAjaxRequest()){
					if (Request.Params["json"] != null){
							varjSonObject = new{
								error = true,
								Message = message
							};
						returnJson(jSonObject);
					}
			 
				ViewBag.Message = message;
				returnPartialView("NoticePartial");
			}
	ViewBag.Message = message;
	return View("NoticePartal");
}

And the NoticePartalview

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<dynamic>" %>
<%   if (ViewBag.Message != null){ %>
		<%=ViewBag.Message%>
<%   }else{%>
            unknown stuff
<%			} %>

RESULTS:

img3

Result for Ajax Request with json parameter not null :

{"paginationIndex":4,"count":4,"error":false,"datas":[
{"studentId":5,"FirstName":"FName5","LastName":"LName5","BirthDay":"\/Date(703683409690)\/"},
{"studentId":6,"FirstName":"FName6","LastName":"LName6","BirthDay":"\/Date(703683409690)\/"},
{"studentId":7,"FirstName":"FName7","LastName":"LName7","BirthDay":"\/Date(703683409690)\/"},
{"studentId":8,"FirstName":"FName8","LastName":"LName8","BirthDay":"\/Date(703683409690)\/"}
]}

Pay Attention:JSon Result and Circular references

Before leaving you, I want to warn about the circular reference. This occurs mostly when you are using a LINQ to SQL class. In these classes, a first object can have a property that references a second object that also references the first object! Do you catch me? No? Okay, I knew it is not easy for the first time you read it. So, read again you will understand. Or see the example bellow.

Think you have two model classes: the StudentModelclass and the ClassroomModel class. A student belongs to a classroom and the classroom object has a list of students. So, if you try to pass this kind of objects to the json() method to serialize it, you will be experience a circular reference error and this will not work.

This is how you avoid it: you can create a supplementary model for each class instead of having strongly typed property, you should have methods such as getStudentPerClassroom() or getStudentClassRoom(). This is one, there are many other solutions. Visit google or stackoverflow.

Summary

This was only to show you how you can take advantage of AllInOneActions, instead of writing three different actions as many developers. So, you can rewrite your actions in order to allow them to serve each kind of request (Ajax request that returns a simple view result, Ajax request that returns a json result,etc.). It is also possible to write this can of actions for the Details, Delete and Edit Actions! As I usually do it.

Use your inspiration and imagination to go far away! Stay safe: no circular reference please.



C# 4.5 Developer ASP.NET 4.5, Php 5, JavaScript (jQuery 1.6), Silverlight 4 (Sooner Beta5) xHtml, html5 Css 3 PhotoShop CS3 Java

What did you think of this post?
Services
[Close]
To have full access to this post (or download the associated files) you must have MrBool Credits.

  See the prices for this post in Mr.Bool Credits System below:

Individually – in this case the price for this post is US$ 0,00 (Buy it now)
in this case you will buy only this video by paying the full price with no discount.

Package of 10 credits - in this case the price for this post is US$ 0,00
This subscription is ideal if you want to download few videos. In this plan you will receive a discount of 50% in each video. Subscribe for this package!

Package of 50 credits – in this case the price for this post is US$ 0,00
This subscription is ideal if you want to download several videos. In this plan you will receive a discount of 83% in each video. Subscribe for this package!


> More info about MrBool Credits
[Close]
You must be logged to download.

Click here to login