Tag Archives: ASP.NET MVC

MvcPaging 2.1

Today, a new version of the MvcPaging library was released. The only new feature in this release is the option to add strongly typed route values.
In the past you had to add extra route values for the page links like this:

@Html.Pager(Model.Items.PageSize, Model.Items.PageNumber, Model.Items.TotalItemCount).Options(o => o
    .AddRouteValue("Filter.Name", Model.Filter.Name)
    .AddRouteValue("Filter.City", Model.Filter.City)
    .AddRouteValue("Filter.PostalCode", Model.Filter.PostalCode)
)

We’re assuming a viewmodel with an ‘Items’ property as the IPagedList and a ‘Filter’ property for extra filter attributes.

From version 2.1.0 you can use the new AddRouteValueFor method to get rid of the strings:

@Html.Pager(Model.Items.PageSize, Model.Items.PageNumber, Model.Items.TotalItemCount).Options(o => o
    .AddRouteValueFor(m => m.Filter.Name)
    .AddRouteValueFor(m => m.Filter.City)
    .AddRouteValueFor(m => m.Filter.PostalCode)
)

It looks like a small new feature, but behind the scenes, we had to make the Pager and related classes model-aware by creating typed versions (Pager<TModel>). This was a relative big change and therefore the version number jump to 2.1. Adding the model-awareness opens up a lot of new extension possibilities.

See https://github.com/martijnboland/MvcPaging for more info or to get the code or get the NuGet package from http://www.nuget.org/packages/mvcpaging.

Update: there is a live demo now at http://demo.taiga.nl/mvcpaging.

Introducing Actya – a .NET CMS that doesn’t get in your way

Actya is a simple open source ASP.NET MVC Content Management System (CMS).

Why on earth would we need another CMS?

Quite often, a CMS is chosen as application framework for custom application development because you’ll get a lot for free: navigation, security and content management (obviously). Custom applications are then developed as modules that run within the context of the CMS. Cuyahoga, the CMS I’ve started  8 years ago works exactly like this.

Rob Conery describes an issue with this solution:

I’ve deployed Big CMS’s before as a solution for clients and every single time we decided to move away. They’re great for getting off the ground – but after a while there’s jus too much friction.

And that’s probably what many of us experience: a CMS gets in the way when your main focus is the custom application. This is the single main reason to create Actya: a CMS that doesn’t get in your way when doing custom development.

CMS as add-on

Actya can act as an add-on library for your application. While developing your custom application in Visual Studio, you can add it with NuGet just like any other library. The first time you run your application after adding Actya, an installer kicks in to ask you where you want to have your CMS data stored, what theme you want to use and which account is the CMS administrator. No further configuration required and nothing has to change in your custom application.

The video below shows this scenario with NuGetGallery as the ‘custom’ application:

Even though Actya is mainly designed to act as an add-on CMS, you can also use it as a simple regular CMS. Download it at from CodePlex downloads page, point an IIS 7+ web site or application to the extracted files, open de site in your browser and the installation starts automatically.

After installation, you can access Actya’s admin pages at http://my-host-or-application/cmsadmin.

RavenDB document database

Here’s the other reason for creating Actya: schema-less NoSQL databases are considered to be ideal for CMS applications because you can put any type of content in it without having to alter a database schema or have some kind of monstrous Entity-Attribute-Value model. I wanted to experience if that claim is true.

Actya uses the .NET NoSQL database RavenDB and it really makes development easier. Not only due to the flexibility of the schema-less design but also to the absence of a mapping layer. Wonderful! A cool feature of RavenDB is the embedded mode where you don’t need a database server at all. Actya uses this mode by default (the data goes in App_Data), but can also connect to an existing RavenDB server.

Requirements

  • ASP.NET 4.0
  • Full-Trust environment

Wanted: Feedback

I’ve released the first alpha version to see if anybody finds this CMS useful. Your feedback will have a have a lot of weight in determining future development. If you have any, please go to http://actya.codeplex.com/discussions and open a discussion with ‘User Feedback’ as topic.

MvcPaging 1.0.2

A new version of the MvcPaging component is available via NuGet with the following changes:

So the core library hasn’t changed much, and in all honesty, I think it’s pretty much done. Please leave a reply if you think otherwise.

What did change substantially is the sample application. It was still very much ASP.NET 1.0 with WebForms views. This is now a proper ASP.NET MVC 3 application with Razor views and the default ASP.NET MVC 4.0 template for look & feel.

 Screenshot

The sample application can be found at GitHub.

Custom Model Binders and Request Validation

In ASP.NET MVC you can create your own model binders to control the way that models are constructed from an HTTP request. For example, if you don’t want any whitespace characters in your model, you can create a custom model binder that trims all whitespace characters when constructing  a model object. You only have to implement the IModelBinder interface and its BindModel method in a class and register it during application startup.

Getting the value from the HTTP request

There are many examples online of how to build a custom model binder. In all these examples you can find a common way of getting a value from the HTTP request:

public class MyModelBinder: IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        if (valueProviderResult != null)
        {
            var theValue = valueProviderResult.AttemptedValue;
    
            // etc...
        }
    }
}

The code above works nicely and you get protection for potential dangerous request values out of the box. Now let’s assume that we want some potential dangerous values like HTML or XML tags in our model. The recommended way is to add an [AllowHtml] attribute to the model property that may contain HTML and no validation happens for that property. Alternatively, it’s possible to add an [ValidateInput(false)] attribute to the controller action that accepts the model with HTML content, but this turns off validation for all model properties.

A potentially dangerous Request.Form value was detected from the client

Wait a minute! Didn’t we just explicitly say to allow those dangerous values? What’s happening?

It appears that a call to bindingContext.ValueProvider.GetValue() in the code above always validates the data, regardless any attributes. Digging into the ASP.NET MVC sources revealed that the DefaultModelBinder first checks  if request validation is required and then calls the bindingContext.UnvalidatedValueProvider.GetValue() method with a parameter that indicates if validation is required or not.

Unfortunately we can’t use any of the framework code because it’s sealed, private or whatever to protect ignorant devs from doing dangerous stuff, but  it’s not too difficult to create a working custom model binder that respects the AllowHtml and ValidateInput attributes:

public class MyModelBinder: IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        // First check if request validation is required
        var shouldPerformRequestValidation = controllerContext.Controller.ValidateRequest && bindingContext.ModelMetadata.RequestValidationEnabled;
        
        // Get value
        var valueProviderResult = bindingContext.GetValueFromValueProvider(shouldPerformRequestValidation);
        if (valueProviderResult != null)
        {
            var theValue = valueProviderResult.AttemptedValue;
    
            // etc...
        }
    }
}

The other required piece is a way to retrieve an unvalidated value. In this example we use an extension method for the ModelBindingContext class:

public static ValueProviderResult GetValueFromValueProvider(this ModelBindingContext bindingContext, bool performRequestValidation)
{
    var unvalidatedValueProvider = bindingContext.ValueProvider as IUnvalidatedValueProvider;
    return (unvalidatedValueProvider != null)
               ? unvalidatedValueProvider.GetValue(bindingContext.ModelName, !performRequestValidation)
               : bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
}

NuGet package for MVC pager

It’s now possible to add the MVC pager to your own project with NuGet.

image

Or from Visual Studio with ‘Manage NuGet Packages…’ and then search for ‘MvcPaging’.

After installing, you can immediately use the Pager HtmlHelper in your views:

image

et voilà!

image

We also have include the IPagedList for your convenience:

image

For more info, check out the original blogpost that started it or the github project page.

Enjoy!