Haack Looks Back
Nice article on the Haacked’s blog (former MS employee !) on .net in 2011.
http://haacked.com/archive/2011/12/26/oss-net-2011.aspx
He missed a few obvious things, but the post has been edited since
.
Mix 2011
A lot of announcements and new stuff released at Mix 2011 !
Haacked.com has more news and of course Scott Hanselman has more info as well.
The new tools will include modernizr to help asp.net mvc developer step into the age of css3.0 and html5.
My favourite videos: http://tinyurl.com/mvcfavs
Asp.net MVC 2.0 around the corner
When you’re reading this article, the fact that Asp.net mvc 2.0 will be released soon won’t come as a surprise. Both Phil Haack and Scott Guthrie amongst others have been blogging about it. I started a new web project recently and was doing the input validation using Xval by Steve Sanderson. I made a leap of faith and upgraded the project to MVC 2.0 because xval had some quirks (or actually the jquery validation plugin did). Luckily those were fixed by MVC’s new build in validation system. The Gu has an excellent post on the subject. I am using the microsoft validation scripts for the client side, and they work very well, even taking culture settings into consideration out of the box.
There is a lot more to MVC 2.0, the templates are nicer. The Html.TextBoxFor(p => p.Id) is very handy, and make the input forms a lot easier to write. The ModelBinding seem to be much better now as well. With 1.0 I sometimes had to some of it by hand, as the binder didn’t grasp what it was supposed to bind. I haven’t run into that in 2.0.
The attributes for Actions / methods in your controller have been streamlined as well. You only need to put [HttpPost] over actions for Form Posts for example. One thing I haven’t used yet but might come in handy on a big project some day might be the Areas. OdeToCode has a nice article on this new feature.
Over at TekPub, Steve Sanderson and Rob Conery are doing an excellent series on MVC and are also going into the new things of 2.0. If you can spare $28,- I highly recommend watching it.
jqGrid Package
A complete package is now available at http://www.jqgrid.com. This was mentioned in a comment on my post about jqgrid, but I thought it was worth a mention here
.
Enjoy !
Devexpress Asp.net MVC Grid
At work we work with Devexpress components for our windows applications. And I have used some like the pivotgrid and the reporting tool in asp.net websites. They are very powerful, but sometimes hard to use. They have so many options and properties, it’s sometimes hard to find the right one.
Last week the devexpress blog showed a screenshot of their upcoming asp.net mvc grid. It looks suspisciously like jQuery’s tablesorter plugin. What wasn’t revealed though, is how this grid hooks up with the controller, what actions you have to implement etc. So I wonder how they’re going to implement the model ‘hookup’ so to speak.
I am not really anxious to get these kind of tools and components for asp.net mvc, as you can already do that stuff using jquery and your ORM of choice, but you never know, maybe they will come up with something nice, that isn’t overcomplicated and bloated
.
Update : Oops that last part suggest that the devexpress components are bloated, but I didn’t intend it that way. They can be a bit complicated to use though, but their support is always willing to send you a bit of example code if you’re stuck.
Anyway I just hope they come up with something that’s ‘in the spirit’ of MVC, if you know what i mean !
Editing in jqGrid with asp.net mvc
Phil Haack already posted how to use the jQuery grid ‘jqgrid’ on his blog haacked.com. What wasn’t covered in that tutorial was editing, so I thought it would be nice to add that here.
To be honest it gave me a bit of a headache, as I had created a sample table that had the ID column as primary key/autonumber field and jqgrid posts back an ID as well. Mind you, that is the ROWID and not the ID of your record. In a demo app. this can easily go unnoticed as those two are the same when you just add a few records.
After reading up in the docs, and trying to add an extra parameter to the save call (which accidently broke the whole grid), I simply added a hidden column that contains the primary key.
The table I used for this demo was a simple Employees table with an id, first and lastname.
Here’s what the javascript looks like:
var lastsel; jQuery("#list").jqGrid({ url: '/GridDemo/GetGridData', datatype: 'json', mtype: 'GET', colNames: ['IdNr','Id', 'FirstName', 'LastName'], colModel: [ { name: 'IdNr', index: 'IdNr', width: 40, align: 'left', editable: true, editrules: { edithidden: true }, hidden: true }, { name: 'Id', index: 'Id', width: 40, align: 'left', editable: false }, { name: 'FirstName', index: 'FirstName', width: 200, align: 'left', editable: true, edittype: 'text', editoptions: { size: 20, maxlength: 30} }, { name: 'LastName', index: 'LastName', width: 300, align: 'left', editable: true, edittype: 'text', editoptions: { size: 20, maxlength: 30}}], onSelectRow: function(id) { if (id && id !== lastsel) { jQuery('#list').restoreRow(lastsel); jQuery('#list').editRow(id, true); lastsel = id; } }, editurl: "/GridDemo/GridSave", pager: jQuery('#pager'), rowNum: 10, rowList: [5, 10, 20, 50], sortname: 'Id', sortorder: "desc", viewrecords: true, imgpath: '/content/themes/steel/images', caption: 'Employees' }); });
The IdNr is the hidden field, with the edithidden: true editrules you make sure it gets posted once a row has been edited. I choose for inline editing, there are other forms of editing in the jqgriddocs.
As you can see the editurl is where the data that has been edited will be posted to. That controller action looks like this (using linq2sql, but ofcourse any type of model will do) :
public ActionResult GridSave(int id,int idnr, string firstName, string lastName) { jQueryGridModelDataContext db = new jQueryGridModelDataContext(); Employee e = db.Employees.SingleOrDefault(p => p.ID == idnr); if (!(e == null)) { e.FirstName = firstName; e.LastName = lastName; db.SubmitChanges(); return Content("true"); } else { return Content("false"); } }
And that’s it, your grid now has editing functionality ! Ofcourse some validation is required in the GridSave function. The javascript could use the callback function after saving and check for the true or false that gets returned from the GridSave action.
Let me know in the comments if you have any questions or if I made some sort of horrible mistake
.
jQuery Search box and Asp.net MVC
This is a simple run through on how to create a fancy search box, that has suggestions underneath the input box, and that also can do autocomplete. For this example I used the Chinook database from codeplex and the Artists table and the autocomplete jquery plug-in that you can find at pengoworks.com.
There are plenty of jQuery plug-ins that do the same thing, I picked this one as it’s very easy to use. As the docs show, the only thing you need to do is hook your input text box up to autocomplete and provide the url where it gets it’s data from. The view looks like this.
<asp:Content ID="headerContent" ContentPlaceHolderID ="headerPlaceHolder" runat ="server"> <script type="text/javascript" src="../../Scripts/jquery.autocomplete.js"></script> <link href="../../Content/jquery.autocomplete.css" rel="stylesheet" type="text/css" /> <script type="text/javascript"> $(document).ready(function() { $("#searchTerm").autocomplete("/Artists/getAjaxResult/"); }); </script> </asp:Content> <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> <h2>Look for an artist</h2> <form action="/Artists/Search" method="post" id="searchForm"> <input type="text" name="searchTerm" id="searchTerm" value="" size="10" maxlength ="30" /> <input type ="submit" value="Search" /> </form> <br /> </asp:Content>
As you can see I usually have a container in the header of the master page where javascript and custom css files go. Note that you should use the Url.Content method so you get the proper urls when you deploy this on a ‘real server’.
Now for the backend, we need an action that returns a string of results to the autocomplete call.
public ActionResult getAjaxResult(string q) { string searchResult = string.Empty; var artists = (from a in _db.Artists where a.Name.Contains(q) orderby a.Name select a).Take(10); foreach (Artist a in artists) { searchResult += string.Format("{0}|\r\n", a.Name); } return Content(searchResult); }
By using linq to sql I get the top 10 results from the database from the Artists table and return that as a string to the autocomplete call. The user’s input string is a string called q that is put into the action as a url parameter like this: artists/getAjaxResult/?q=symphony. In order to make that work, you need to add a route to the routes table.
routes.MapRoute( "ArtistSearch", "Artists/Search/{searchTerm}", new { controller = "Artists", action = "Search", searchTerm = "" } ); routes.MapRoute( "ArtistAjaxSearch", "Artists/getAjaxResult/", new { controller = "Artists", action = "getAjaxResult" } );
The first route is used once the user has pressed the submit button, the ArtistAjaxSearch is used for the autocomplete script.
So what happens when the user presses the submit button, whether or not he picked an item from the autocomplete results ?
[AcceptVerbs(HttpVerbs.Post)] public ActionResult Search(string searchTerm) { if (searchTerm == string.Empty) { return View(); } else { // if the search contains only one result return details // otherwise a list var artists = from a in _db.Artists where a.Name.Contains(searchTerm) orderby a.Name select a; if (artists.Count() == 0) { return View("notfound"); } if (artists.Count() > 1) { return View("List", artists); } else { return RedirectToAction("Details", new { id = artists.First().ArtistId }); } } }
As you can see, when a single result is found the details view is shown to the user, by using a redirect to the details method. If there is more than one result, the list of artists is shown. When nothing is found, a simple message is shown. You can of course move the search term to that view as well, to show the user what input he did etc., but that is straightforward stuff.
Another way to do this, would be to insert the artist table as an array and let the autocomplete script use those values for it’s magic, all on the client side. This would be doable as long as that table wouldn’t get too long. If there are 1000s of records, this wouldn’t be a very good solution
.
Hope this helps someone out there
, feel free to add any comments or questions !
jQuery-Ui Tabs and Asp.net MVC
Clay made a comment on my previous post and asked how I would use asp.net mvc with jQuery-UI’s tabs. I have slapped together an example project that shows how you could implement the tabs in an asp.net mvc web site. I created an ajax and a regular tab example.
Basically I use a partial view for each tab. This partial view is then also used for the ajax response.
<div id="tabs">
<ul>
<li><a href="#tabs-1">Text 1</a></li>
<li><a href="#tabs-2">Text 2</a></li>
<li><a href="#tabs-3">Text 3</a></li>
</ul>
<div id="tabs-1">
< % Html.RenderPartial("_tab1", Model); %></div>
<div id="tabs-2">
< % Html.RenderPartial("_tab2", Model); %></div>
<div id="tabs-3">
< % Html.RenderPartial("_tab3", Model); %></div>
</div>
There is no database access in the example project, I sort of simulated a database by using a service model that provides the viewmodel that holds the texts that are displayed in the three tabs.
Regarding the ajax controller method, it would of course be better to not get the entire viewmodel in a real world situation and then pass that on to the view, but since this is a brief demo I thought I could get away with this in this example
.
public ActionResult getAjaxTab(int id)
{
string viewName = string.Empty;
TabExample.Services.tabTextService serv = new TabExample.Services.tabTextService();
tabViewModel myModel = serv.getTabViewModel();
switch (id)
{
case 1:
viewName = "_tab1";
break;
case 2:
viewName = "_tab2";
break;
case 3:
viewName = "_tab3";
break;
default:
viewName = "_error";
break;
}
System.Threading.Thread.Sleep(1000);
return PartialView(viewName, myModel);
}
I am using this js function to update the tabs.
function getContentTab(index) {
var url='< %= Url.Content("~/Home/getAjaxTab") %>/' + index;
var targetDiv = "#tabs-" + index;
var ajaxLoading = "<img id='ajax-loader' src='<%= Url.Content("~/Content") %/>/ajax-loader.gif' align='left' height='28' width='28'>";
$(targetDiv).html("
" + ajaxLoading + " Loading...
");
$.get(url,null, function(result) {
$(targetDiv).html(result);
});
}
There is a select event on the tabs that you can hook into as well, I just find it easier to just use the onclick event of the tab div’s.
Hope this is some help to anybody out there, it was fun to create this small project. If anyone has any suggestions, or questions let me know in the comments !
jQuery-ui 1.7 and Asp.net MVC
The news of a new jQuery-ui 1.7 release came in through twitter ! The asp.net mvc application I am working on at the moment uses various jquery-ui things, like the accordeon and the datepicker, and some of the icons, but it was a bit messy to actually get it to work. Some of the images were named wrong and the paths didn’t quite work.
The Content and Script folder had become a big mess as well. Luckily with 1.7 that has all passed, I removed the previous version and all images, and inserted the 1.7 smoothness theme. Changed the css and jquery ui calls in the master view and it worked out of the box ! No need to hack around anymore, no image renaming etc… Gratz to the jQuery-ui team for delivering such a nice product.
<link href="../../Content/Site.css" rel="stylesheet" type="text/css" /> <link href="../../Content/Theme_Red/jquery-ui.css" rel="stylesheet" type="text/css" /> <link href="../../Content/jquery-ui.custom.css" rel="stylesheet" type="text/css" />
If you want to make any changes to the ui, for example I added some padding to the ui-state-error and ui-state-highlight classes, make sure to put them in a seperate file and load them after the included jquery-ui.css file. That way if you change themes or if there is an update, your changes will remain.
CSS Font-Size and Font
There is an odd issue with font-size: and font: in css. I am using the cutline pro 1.4 theme on my eve-blog, and edited the comment section of that theme. IE8 and Google Chrome both showed the fonts real small where as Firefox 3 picked it up the way I intended. Turns out the font: description was not overwritten by font-size in the css file.
Original
body {
font: 62.5% Georgia, "Times New Roman", Times, serif;
}
comment {
font-size: 1.4em;
}
Cleaned up:
body {
font-size: 62.5%;
font-family: Georgia, "Times New Roman", Times, serif;
}
And now it’s fixed
.

