Saturday, February 15, 2014

ASP.NET MVC 5.1 Throttling Filter

With MvcThrottle you can protect your site from aggressive crawlers, scraping tools or unwanted traffic spikes originated from the same location by limiting the rate of requests that a client from the same IP can make to your site or to specific routes. MvcThrottle is compatible with ASP.NET MVC 5.1 and can be installed via NuGet, the package is available at nuget.org/packages/MvcThrottle.

You can set multiple limits for different scenarios like allowing an IP to make a maximum number of calls per second, per minute, per hour or per day. You can define these limits to address all requests made to your website or you can scope the limits to each Controller, Action or URL, with or without query string params.
MvcThrottle filter is designed for controlling the rate of requests that clients can make to a website based on IP address, request route and client identity. You can set multiple limits for different scenarios like allowing an IP to make a maximum number of calls per second, per minute, per hour or per day. You can define these limits to address all requests made to your website or you can scope the limits to each Controller, Action or URL, with or without query string params.
Global throttling based on IP
The setup bellow will limit the number of requests originated from the same IP.
If from the same IP, in same second, you’ll make a call to 
home/index and home/about the last call will get blocked.
public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        var throttleFilter = new ThrottlingFilter
        {
            Policy = new ThrottlePolicy(perSecond: 1, perMinute: 6, perHour: 9, perDay: 90)
            {
                IpThrottling = true
            },
            Repository = new CacheRepository()
        };

        filters.Add(throttleFilter);
    }
}
In order to enable throttling you’ll have to decorate your Controller or Action withEnableThrottlingAttribute, if you want to exclude a certain Action you can applyDisableThrottingAttribute.

[EnableThrottling]
public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    [DisableThrotting]
    public ActionResult About()
    {
        return View();
    }
}
You can define custom limits using the EnableThrottling attribute, these limits will override the default ones.
[EnableThrottling(PerSecond = 2, PerMinute = 10, PerHour = 30)]
public ActionResult Index()
{
    return View();
}

Endpoint throttling based on IP
If, from the same IP, in the same second, you’ll make two calls to home/index, the last call will get blocked.
But if in the same second you call 
home/about too, the request will go through because it’s a different route.
var throttleFilter = new ThrottlingFilter
{
    Policy = new ThrottlePolicy(perSecond: 1, perMinute: 10, perHour: 60)
    {
        IpThrottling = true,
        EndpointThrottling = true,
        EndpointType = EndpointThrottlingType.ControllerAndAction
    },
    Repository = new CacheRepository()
};

Friday, February 14, 2014

Custom Model Binder in MVC

What is a model binder?

As we know, we can pass data from action to view through view data and view model. It's not one way and you can post data from view to action via form parameters, querystring, route parameters and etc. Model binders bind model to these data. All model binders implement IModelBinder interface directly or indirectly.                   

Custom model binders

Model binding is also one of the extensibility points in the MVC framework. If you can’t use the default binding behaviour you can provide your own model binders, and mix and match binders. To implement a custom model binder you need to implement the IModelBinder interface.

Use Case

Let us take an example where we have 3 text boxes which accepts day, month and year for a date but on submission of form we want our custom model binder to bind day,month and year in single date property.


Implementing IModelBinder

    public class CustomDateBinder : IModelBinder
    {
        Public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            HttpRequestBase request = controllerContext.HttpContext.Request;

            string title = request.Form.Get("Title");
            string day = request.Form.Get("Day");
            string month = request.Form.Get("Month");
            string year = request.Form.Get("Year");

            return new DateModel()
            {
                Title = title,
                Date = day + "/" + month + "/" + year
            };
        }
    }

Our Date Model is as follows,

   
public class DateModel
    {
        public string Title { get; set; }
        public string Date { get; set; }
    }

And Our Action is as follows,
        [HttpPost]
        public ActionResult CustomBinder(DateModel model)
        {
            return View();
        }

Put the following line of code in the Application_Start() of our global.asax

ModelBinders.Binders.Add(typeof(DateModel), new CustomDateBinder());

This tells MVC anytime we have a typeof(DateModel) as a parameter in an action. We should use the CustomDateBinder to try and create an object to fill the DateModel.

Output:



And on submission have a look at model,