ASP.NET Web Forms Extensibility: Model Binding Value Providers

ASP.NET 4.5 introduced model binding: basically, it is a way for databound controls - Repeater, GridView, ListView, etc - to be fed, not from a datasource control - ObjectDataSource, EntityDataSource, SqlDataSource, etc -, but from a method in the page. This method needs to return a collection, and may have parameters. The problem is: how these parameters get their values? The answer is: through a model binding value provider.

A model binding value provider is a class that implements IValueProvider, and normally is injected through a ValueProviderSourceAttribute-derived attribute. ASP.NET includes some implementations:

If we want, say, to return a value from the Common Service Locator, it's pretty easy. First, an attribute:

[Serializable]
[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)]
public sealed class ServiceLocatorAttribute : ValueProviderSourceAttribute
{
    private readonly Type serviceType;
    private readonly String key;
 
    public ServiceLocatorAttribute(Type serviceType, String key = null)
    {
        this.serviceType = serviceType;
        this.key = key;
    }
 
    public override IValueProvider GetValueProvider(ModelBindingExecutionContext modelBindingExecutionContext)
    {
        return new ServiceLocatorValueProvider(this.serviceType, this.key);
    }
}

And now the actual value provider:

public sealed class ServiceLocatorValueProvider : IValueProvider
{
    private readonly Type serviceType;
    private readonly String key;
 
    public ServiceLocatorValueProvider(Type serviceType, String key)
    {
        this.serviceType = serviceType;
        this.key = key;
    }
 
    public Boolean ContainsPrefix(String prefix)
    {
        return true;
    }
 
    public ValueProviderResult GetValue(String key)
    {
        return new ValueProviderResult(ServiceLocator.Current.GetInstance(this.serviceType, this.key), null, CultureInfo.CurrentCulture);
    }
}

You can even have the ServiceLocatorAttribute implement the IValueProvider interface, I just separated it because conceptually they are different things.

Finally, here's how we would use it:

public IQueryable<SomeEntity> GetItems([ServiceLocator(typeof(MyComponent), "SomeKey")] MyComponent cmp)
{
    //do something
}

Pretty sleek, don't you think? Winking smile

                             

No Comments

Add a Comment

As it will appear on the website

Not displayed

Your website