Recently I was engaged in porting a project from “normal” ASP.NET to ASP.NET MVC. I decided to try to make it beautiful and asynchronous due to the development of technology. This post is about what and how I wrote, and what came of it.
Technology selection
Now, for some reason, all those who are not too lazy to rewrite sites on MVC benefit it looks more elegant and works faster - a consequence of the Ajax phenomenon as well as the worldwide distribution of jQuery. Faced with the same task (as well as very tight deadlines), I decided to try it too. In terms of technology, I chose the following:
- Asp.Net MVC and Default ViewEngine. Despite the fact that Spark is cool, de facto, creating a “rich UI” still falls on server-side servers, so “beautiful tags” would be appropriate only if I would generate, say, ordinary labels instead of Ajax-oriented ones.
- jQuery Of course there is the same ASP.NET AJAX and interesting things like Ajax.LinkAction () , etc., but without having much experience in either, I decided to follow the crowd. Perhaps it will be time to explore options from Microsoft.
- jQuery UI . JQuery Super Library, which makes a very nice user interface. I personally needed a calendar.
- Telerik Extensions for ASP.NET MVC for tables and tab controls. Why Telerik? I liked the simple, intuitive API and a very good-looking interface. Also pleased with the fact that developers with the status of MVP receive free licenses - we have a team of 3 people such two, so it turns out a good savings.
Nb: for open source projects, these components can be used for free.
Having access to all the components, I proceeded to the assembly. Below I will describe the most key and useful aspects that may be useful to other developers.
Work with tables

My main goal when working with third-party components was to obtain asynchronous table filling. In principle, in order to get the actual data for a table, you need to pull out some
IEnumerable <X> and pass it to the view, right? No, not at all.
If something on the page picks up objects through Ajax, then the format of these objects should be very primitive. It is not the same as if we used a strongly typed representation. Everything should be quite primitive.
Let's start with the table itself. The table (at least in the Telerik approach) is created using cunning C # constructs in the view.
<%= Html.Telerik().Grid<PersonRow>().Name( "PersonGrid" ).Columns(cs =><br/>
{<br/>
cs.Add(i => i.Name).Title( "Name" );<br/>
cs.Add(i => i.Gender).Title( "Gender" );<br/>
}).Ajax(ajax => ajax.Enabled( true ).Action( "GetPeople" , "Home" ))<br/>
.Pageable(pager => pager.PageSize(20).Position(GridPagerPosition.Bottom))<br/>
%><br/>
The code above defines a table with two columns, while for presentation it uses not
Person (this is what we get from the database), but
PersonRow , i.e. the model which, from
Person, pulls out everything it needs and stores - guess what - just strings! Because we can’t add any additional logic to the code above.
// js, !<br/> cs.Add(i => i.IsMale ? "Male" : "Female" ).Title( "Gender" );<br/>
So, our asynchronous table takes data from the controller method. This method, of course, does not return an
IEnumerable <PersonRow>, but a modest
ActionResult . So that everything becomes clear, here's a bit of code:
[GridAction]<br/>
public ActionResult GetPeople()<br/>
{<br/>
return View( new GridModel<EventRow> {<br/>
Data = repository.GetPeople().Select(p => new PersonRow(p))<br/>
});<br/>
}<br/>
It is interesting that these two pieces of code (on the page and in the controller) are practically all that is needed to load a table asynchronously. Being ajax-driven, the label can be updated from the same jQuery. This is done simply:
$( '#PersonGrid' ).data( 'tGrid' ).ajaxRequest();<br/>
Calling ajax methods via jQuery
Since I decided to use jQuery, I needed to learn how to invoke page methods using ajax. I had to send the data from the form and receive the data. To get the data, I used the json format, i.e. my methods on the controller side took a set of parameters (like regular controller actions), and returned
JsonResult .
public JsonResult FindPersonName( string id)<br/>
{<br/>
try <br/>
{<br/>
string name = repository.FindById( int .Parse(id)).Name;<br/>
return Json( new {Result = Name, Success = true });<br/>
}<br/>
catch (Exception ex)<br/>
{<br/>
return Json( new {Result = "Could not find person. " + ex.Message, Success = false });<br/>
}<br/>
}<br/>
The code above returns the result regardless of whether there was an exception or not, which is problematic for us, because we need to handle as many as three different situations:
- Request successful
- On the server side there was an exception and Success == false
- It didn’t come to the server, the ajax call fell on the client
Now let's talk about calling this method from jQuery. Here we have a “colorful” call that shows the processing of a user clicking on a specific hyperlink:
$( '#lnkFindName' ).click(function( event ) {<br/>
$.ajax({<br/>
type: "POST" ,<br/>
contentType: "application/x-www-form-urlencoded" ,<br/>
url: "/Home/FindPersonName/" ,<br/>
dataType: "json" ,<br/>
data: {<br/>
id: $( '#personId' ).val()<br/>
},<br/>
success: function(msg, status) {<br/>
if (msg[ 'Success' ] == true ) {<br/>
$( '#personName' ).val(msg[ 'Result' ]);<br/>
}<br/>
else {<br/>
$( '#statusBox' ).html(msg[ 'Result' ]).fadeIn();<br/>
}<br/>
},<br/>
error: function(msg, status) {<br/>
$( '#statusBox' ).html(msg.statusText).fadeIn();<br/>
}<br/>
});<br/>
});<br/>
As you can see, json goes both ways, and quite successfully - after receiving the message, we pull out the information via
msg ['key'] . In the example above, all three options for the completion of the request are processed.
')
Conclusion
I have to say that using jQuery-based tools is very simple. And the interaction through ajax is extremely understandable when working with well-designed components. It is not strange, my first ajax-damn thing did not come out. :)