Tag Archives: ASP.Net

Basic AJAX with MVC3 & Razor

Suppose you have a page which requires you to load content inline in response to some action.  In the below example, you have a filter and a “preview” button which needs to show some sample data.

You could have the button do a post and have the MVC handler parse the form fields and render the view with the data you want to show.  But, you may have a complex page with many tabs and want to optimize form performance.    In such a case, you want to send just the form data for the current tab and inject the response into the current page.  Here is how to do that:

Here is the HTML of the relevant section of the “Export” tab:

<fieldset>        
 
<div class="btn green preview">
<a href="#">Preview</a></div>
<div class="clear"></div>
 
<span>&nbsp;</span>    
</fieldset>
 
<div class="btn orange submit">
<a href="#">Export to CSV</a></div>
<div class="clear"></div>

Note the two href’s with attributes of btn.  Here is the relevant JavaScript:

$(document).ready(function () {
 
    $('.preview').click(function () {
        $('#preview').html('<strong>Loading...</strong>');
        $.post('Home/Preview/?' + $(this).closest("form").serialize(), function (data) {
            $('#preview').html(data);
        });
    });
 
    $('.submit').click(function () {
        $('.submit a').html("Loading...");
        $(this).closest("form").submit();
        return false;
    });
 
});

The “Export” button submits the entire form.  The “Preview” button on the other hand:

  1. Shows the “loading” text.
  2. Serializes the content of the parent form
  3. Posts the serialized content to a url
  4. Renders the response from that URL in the designated div

Here is Preview.cshtml:

@{
    Layout =null;
}
@model  Models.ExportFilter
 
<h2>@ViewBag.Message</h2>
 
<strong>Name, Source, Email, DateAdded</strong>
<ul>
    @foreach (var item in Model.MarketingList)
    {
	<li>@item.FirstName, @item.Source, @item.Email, @item.DateAdded.ToShortDateString()</li>
    }&nbsp;
</ul>&nbsp;

Note that I am overriding the default Layout because I don’t want to show the normal header/footer. _Blank.cshtml contains solely “@RenderBody()”

The handler for the /Preview target is:

[HttpPost]
        public ActionResult Preview(ExportFilter filter)
        {
            var export = new EmailExporter(filter);
            List emailList = export.Process();
            ViewBag.Message = string.Format("{0:##,#} records to be exported", emailList.Count); 
            return View(filter); 
        }

Now when I click “preview”, I get a momentary “loading” screen and then the rendered view.

Creating a Stanza Catalog with ASP.Net MVC 2.0

Stanza is a book reader for the iPhone/iPad.  One of Stanza’s features is the ability to browse specially formatted book catalogs.  While it has a number of built-in catalogs, you can also add your own.  I have created such a catalog with ASP.Net MVC 2.0 (screenshots).  The Stanza catalog format is pretty simple – just AtomPub with some proprietary attributes for images and things like search.  This was a quick and easy project because the .Net Framework 4.0 has the System.ServiceModel.Syndication namespace which does all the RSS/Atom feed generation.  We just have to add some custom attributes and serialize the feed to the browser.

Here is a quick overview of the code (Links are to the latest version of the source code in my SVN browser.  You can get the project from SVN here (guest/guest).)  The LiteratureCatalog and LiteratureCatalog.Tests projects have the relevant code.

Update: The Stanza catalog format works equally well with Aldiko, an e-reader for Android.

CatalogController.cs:

This is the default controller specified in global.asax.  It defers to MisesFeeds to generate the feed items and to FeedResult to serialize and write out the feed.

Sample Method:

public FeedResult Journal(int journalId)
{
var feeds = new MisesFeeds(Request);
SyndicationFeed feed = feeds.GetJournalFeed(journalId);
 
return new FeedResult(new Atom10FeedFormatter(feed));
}

MisesFeeds.cs

MisesFeed contains all the code to generate a SyndicationFeed object containing a List of SyndicationItem.  Note the Stanza-specific links added in search list-builder and the final helper method:

item.Links.Add(new SyndicationLink(new Uri(DataFormat.GetAbsoluteURL(p.Logo)),
"x-stanza-cover-image-thumbnail""""image/jpeg"0));
public SyndicationFeed CreateFeedFromSyndicationItemList(IEnumerable postItems, string title,
string description)
{
var feed = new SyndicationFeed(title, description, new Uri(feedUri), postItems)
{
Copyright = new TextSyndicationContent(Configuration.Copyright),
Language = "en-US"
};
 
var self = new SyndicationLink(new Uri(Host + HttpUtility.UrlEncode("/Catalog/"))"self""", Type, 0);
feed.Links.Add(self);
 
feed.Links.Add(new SyndicationLink(new Uri(Host + "/Catalog/Search/?q={searchTerms}",true),"search","Search Catalog",Type,0));
 
return feed;
}

FeedResult.cs:

FeedWriter inherits from ActionResult.  It just writes the SyndicationFeed out with an XmlTextWriter:

public override void ExecuteResult(ControllerContext context)
{
if (context == null)
throw new ArgumentNullException("context");
 
HttpResponseBase response = context.HttpContext.Response;
 
response.ContentType = !string.IsNullOrEmpty(ContentType) ? ContentType : "application/atom+xml";
 
if (ContentEncoding != null)
response.ContentEncoding = ContentEncoding;
 
if (feed != null)
using (var xmlwriter = new XmlTextWriter(response.Output))
{
xmlwriter.Formatting = Formatting.Indented;
feed.WriteTo(xmlwriter);
}
}

Thanks to DamienG for the FeedResult class.

To see the catalog, get the Stanza app, tap “Get Books”, “Shared”, “Add Book Source”, then add the URL mises.org/catalog.

Luhn algorithm validation via a CustomValidator control

The Luhn algorithm is a checksum used for credit cards and many other identifying numbers as a basic integrity validation check.  It’s useful for credit card forms because it avoids unneeded transaction attempts when card numbers are mis-typed.
It’s easy to add an account # Luhn checksum validation control to credit card forms in ASP.Net:
  • Add this method to your business logic.
  • Add a <asp:CustomValidator  … /> control with the error message, target control, etc.
  • Add and wire up a void ServerValidation method:
void ServerValidation(object source, ServerValidateEventArgs args) {
// use a RequiredFieldValidator to check for an empty value
 if (txtCardNum.Text == string.Empty) args.IsValid = true;
 args.IsValid = IsCreditCardValid(this.txtCardNum.Text);
}
 
protected override void OnInit(EventArgs e)    {
 base.OnInit(e);
 valLunCode.ServerValidate += ServerValidation;
}
  • (Optional:) For client-side code, use a Javascript version from here.