Looking at ASP.NET MVC 5.1 and Web API 2.1 – Part 3 – Bootstrap and JavaScript enhancements

Spread the love
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  

This is part 3 of a 4 part series covering some of the new features in the ASP.NET MVC 5.1 and Web API 2.1 releases.

Part 1: Overview and Enums

Part 2: Attribute Routing with Custom Constraints

Part 3: Bootstrap and JavaScript enhancements

Part 4: Web API Help Pages, BSON, and Global Error Handling

In this post, we’ll be focusing on some client-side improvements to ASP.NET MVC 5.1.

As a reminder if you haven’t read the first post, these updates are currently delivered via a NuGet update to your existing ASP.NET MVC 5 / Web API 2 applications. They’ll be part of the File / New Project templates included in an upcoming Visual Studio update.
EditorFor now supports passing HTML attributes – Great for Bootstrap
The new ASP.NET project templates all include Bootstrap themes. Bootstrap uses custom class names for everything – styling, components, layout, behavior. That made it frustrating that you couldn’t pass classes down to the Html.EditorFor HTML helper: you either had to use specific HTML Helpers like Html.TextBoxFor (which do allow you to pass HTML attributes, but don’t benefit from some of the other nice features in HTML.EditorFor, like Data Attribute support for display and input validation) or give up on using the Bootstrap classes and style things yourself.

In the 5.1 release, you can now pass HTML attributes as an additional parameter to Html.EditorFor, allowing you to get the best of both. Here’s an example of why that’s useful.

In the first post in the series, we scaffolded a simple create controller and associated views. The Create view ended up looking like this:

That’s okay, but it’s not taking advantage of any of the Bootstrap form styling (e.g. focus indication, element sizing, groups, etc.) and it won’t do anything special with custom Bootstrap themes. A great start would be just to add the “form-control” class to the form elements. That just involves changing from this:

@Html.EditorFor(model => model.FirstName)

to this:

@Html.EditorFor(model => model.FirstName, new { htmlAttributes = new { @class = “form-control” }, })

When I make that update to the textboxes, I get this view:

You’ll notice some subtle improvements, like the focus highlight on the FirstName field, nicer textbox size and validation layout for Age, etc. These are just really simple things with a  very basic model, but they give a quick idea of the improvement here.

Also nice is that I can pass the attributes on Html.EditorFor when displaying the entire model. Here I’ve updated the entire form section to just use one EditorFor call, passing in the model:

@using (Html.BeginForm())
{
@Html.AntiForgeryToken()

Person

@Html.ValidationSummary(true)
@Html.EditorFor(model => model, new { htmlAttributes = new { @class = “form-control” }, })

}

Note that to make sure the Id property didn’t display and to use the custom radio enum display template (as explained in the first post in the series), I added two annotations to my model. Here’s how the model and associated Enum look:

public class Person
{
[ScaffoldColumn(false)]
public int Id { get; set; }
[UIHint(“Enum-radio”)]
public Salutation Salutation { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
//I guess technically these are called honorifics
public enum Salutation : byte
{
[Display(Name = “Mr.”)] Mr,
[Display(Name = “Mrs.”)] Mrs,
[Display(Name = “Ms.”)] Ms,
[Display(Name = “Dr.”)] Doctor,
[Display(Name = “Prof.”)] Professor,
Sir,
Lady,
Lord
}

That gives me the exact same output as shown above (the second, nicer screenshot). What’s cool there is that the EditorFor method passed that form-control class to each element in the form, so each input tag got the form-control class. That means that I could apply additional Bootstrap classes, as well as my own custom classes, in that same call:

@Html.EditorFor(model => model, new { htmlAttributes = new { @class = “form-control input-sm my-custom-class” }, })

You can see the code changes and associated tests for this EditorFor change on this commit on CodePlex.

Client-side validation for MinLength and MaxLength

This is a pretty straightforward one: we had client-side validation for StringLength before, but not for MinLength and MaxLength. Personally, I feel like it’s a tossup on which to use – StringLength lets you set both min and max and is more widely supported, but MinLength and MaxLength allow you to specify them separately and give different validation messages for each. Regardless, the good news is that whichever you use, they’re both supported on both server and client.

To test that out, we’ll add some MinLength and MaxLength attributes to our Person class.

public class Person
{
[ScaffoldColumn(false)]
public int Id { get; set; }
[UIHint(“Enum-radio”)]
public Salutation Salutation { get; set; }
[Display(Name = “First Name”)]
[MinLength(3, ErrorMessage = “Your {0} must be at least {1} characters long”)]
[MaxLength(100, ErrorMessage = “Your {0} must be no more than {1} characters”)]
public string FirstName { get; set; }
[Display(Name = “Last Name”)]
[MinLength(3, ErrorMessage = “Your {0} must be at least {1} characters long”)]
[MaxLength(100, ErrorMessage = “Your {0} must be no more than {1} characters”)]
public string LastName { get; set; }
public int Age { get; set; }
}

I get immediate feedback on what the website thinks of a potential stage name I’ve been considering:

Here’s the link to the work item, and here’s the code diff for the commit.

Three small but useful fixes to Unobtrusive Ajax

There are a few fixes to Unobtrusive Ajax:

Support “this” context for ajax actions/forms

Unobtrusive.Ajax interferes with the cancel convention on validation

ASP.NET MVC 3 LoadingElementDuration is not working
I thought the first fix was pretty interesting: a question came up on StackOverflow, someone posted a suggested one line fix on a CodePlex issue, and it got fixed in this commit.

This issue allows callbacks from Unobtrusive Ajax to have access to the initiating element.  That’s pretty handy when you’ve got multiple potential callers, e.g. a list of items which contain Ajax.ActionLink calls. In the past, I’ve had to write unnecessarily complicated JavaScript to wire things up manually because I couldn’t take advantage of the OnBegin, OnComplete, OnFailure and OnSuccess options, e.g.

$(function () {
// Document.ready -> link up remove event handler
$(“.RemoveLink”).click(function () {
// Get the id from the link
var recordToDelete = $(this).attr(“data-id”);
if (recordToDelete != ”) {
// Perform the ajax post
$.post(“/ShoppingCart/RemoveFromCart”, {“id”: recordToDelete },
function (data) {
// Successful requests get here
// Update the page elements
if (data.ItemCount == 0) {
$(‘#row-‘ + data.DeleteId).fadeOut(‘slow’);
} else {
$(‘#item-count-‘ + data.DeleteId).text(data.ItemCount);
}
$(‘#cart-total’).text(data.CartTotal);
$(‘#update-message’).text(data.Message);
$(‘#cart-status’).text(‘Cart (‘ + data.CartCount + ‘)’);
});
}
});
});

Now with this change, I’d have the option of wiring up the Ajax call and success callbacks separately and tersely, since they’d have access to the calling element for the ID.

That’s it for this post, in the next (and definitely last) post of this series I’ll look at some ASP.NET Web API 2.1 improvements.

X ITM Cloud News

Ana

Next Post

weblogs.asp.net Now Running On Orchard and Azure Web Sites

Mon Nov 25 , 2019
Spread the love          I’m incredibly happy to announce that my blog – and all 750 other blogs running under weblogs.asp.net – are now powered by Orchard and Azure Web Sites! That’s 750 blogs, all hosted in 4 Azure Web Sites all running on only one large virtual machine. A bit of […]
X- ITM

Cloud Computing – Consultancy – Development – Hosting – APIs – Legacy Systems

X-ITM Technology helps our customers across the entire enterprise technology stack with differentiated industry solutions. We modernize IT, optimize data architectures, and make everything secure, scalable and orchestrated across public, private and hybrid clouds.

This image has an empty alt attribute; its file name is x-itmdc.jpg

The enterprise technology stack includes ITO; Cloud and Security Services; Applications and Industry IP; Data, Analytics and Engineering Services; and Advisory.

Watch an animation of  X-ITM‘s Enterprise Technology Stack

We combine years of experience running mission-critical systems with the latest digital innovations to deliver better business outcomes and new levels of performance, competitiveness and experiences for our customers and their stakeholders.

X-ITM invests in three key drivers of growth: People, Customers and Operational Execution.

The company’s global scale, talent and innovation platforms serve 6,000 private and public-sector clients in 70 countries.

X-ITM’s extensive partner network helps drive collaboration and leverage technology independence. The company has established more than 200 industry-leading global Partner Network relationships, including 15 strategic partners: Amazon Web Services, AT&T, Dell Technologies, Google Cloud, HCL, HP, HPE, IBM, Micro Focus, Microsoft, Oracle, PwC, SAP, ServiceNow and VMware

.

X ITM