Sorted By: Month (3) and Year (2012)

Slides of My MS Web Platform & ASP.NET MVC 101 Talks

Today, I was at Computer Engineering Department of Mugla University and I gave two introduction talks on MS Web Platform and ASP.NET MVC 101.
2012-03-23 17:23
Tugberk Ugurlu


Today, I was at Computer Engineering Department of Mugla University and I gave two introduction talks on MS Web Platform and ASP.NET MVC 101. I would like to thank Selin Kirik who organized this event.

The slides and codes can be downloaded from the below links.

Credits: I stole some content from @shanselman’s pervious talks to use in the slides and the slide template belongs to MIX11. I also used a picture of Eric Sowell and I encourage you to check that picture out Winking smile

Creating Custom CSVMediaTypeFormatter In ASP.NET Web API for Comma-Separated Values (CSV) Format

In this post, we will see how to create a custom CSVMediaTypeFormatter in ASP.NET Web API for comma-separated values (CSV) format
2012-03-22 08:09
Tugberk Ugurlu


As I tried to explain on my previous MediaTypeFormatters With MediaTypeMappings post, formatters play a huge role inside the ASP.NET Web API processing pipeline. As Web API framework programming model is so similar to MVC framework, I kind of want to see formatters as views. Formatters handles serializing and deserializing strongly-typed objects into specific format.

I wanted to create CSVMediaTypeFormatter to hook it up for list of objects and I managed to get it working. After I created it, I saw the great Media Formatters post on ASP.NET web site which does the same thing. I was like "Man, come on!" and I noticed that formatter meant to be used with a specific object, so I figured there is still a validity in my implementation.

Here is the drill:

First of all we need to create a class which will be derived from MediaTypeFormatter abstract class. Here is the class with its constructors:

public class CSVMediaTypeFormatter : MediaTypeFormatter {

    public CSVMediaTypeFormatter() {

        SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/csv"));
    }
    
    public CSVMediaTypeFormatter(
        MediaTypeMapping mediaTypeMapping) : this() {

        MediaTypeMappings.Add(mediaTypeMapping);
    }
    
    public CSVMediaTypeFormatter(
        IEnumerable<MediaTypeMapping> mediaTypeMappings) : this() {

        foreach (var mediaTypeMapping in mediaTypeMappings) {
            MediaTypeMappings.Add(mediaTypeMapping);
        }
    }
}

Above, no matter which constructor you use, we always add text/csv media type to be supported for this formatter. We also allow custom MediaTypeMappings to be injected.

Now, we need to override two methods: MediaTypeFormatter.CanWriteType and MediaTypeFormatter.OnWriteToStreamAsync.

First of all, here is the CanWriteType method implementation. What this method needs to do is to determine if the type of the object is supported with this formatter or not in order to write it.

protected override bool CanWriteType(Type type) {

    if (type == null)
        throw new ArgumentNullException("type");

    return isTypeOfIEnumerable(type);
}

private bool isTypeOfIEnumerable(Type type) {

    foreach (Type interfaceType in type.GetInterfaces()) {

        if (interfaceType == typeof(IEnumerable))
            return true;
    }

    return false;
}

What this does here is to check if the object has implemented the IEnumerable interface. If so, then it is cool with that and can format the object. If not, it will return false and framework will ignore this formatter for that particular request.

And finally, here is the actual implementation. We need to do some work with reflection here in order to get the property names and values out of the value parameter which is a type of object:

protected override Task OnWriteToStreamAsync(
    Type type,
    object value,
    Stream stream,
    HttpContentHeaders contentHeaders,
    FormatterContext formatterContext,
    TransportContext transportContext) {

    writeStream(type, value, stream, contentHeaders);
    var tcs = new TaskCompletionSource<int>();
    tcs.SetResult(0);
    return tcs.Task;
}

private void writeStream(Type type, object value, Stream stream, HttpContentHeaders contentHeaders) {

    //NOTE: We have check the type inside CanWriteType method
    //If request comes this far, the type is IEnumerable. We are safe.

    Type itemType = type.GetGenericArguments()[0];

    StringWriter _stringWriter = new StringWriter();

    _stringWriter.WriteLine(
        string.Join<string>(
            ",", itemType.GetProperties().Select(x => x.Name )
        )
    );

    foreach (var obj in (IEnumerable<object>)value) {

        var vals = obj.GetType().GetProperties().Select(
            pi => new { 
                Value = pi.GetValue(obj, null)
            }
        );

        string _valueLine = string.Empty;

        foreach (var val in vals) {

            if (val.Value != null) {

                var _val = val.Value.ToString();

                //Check if the value contans a comma and place it in quotes if so
                if (_val.Contains(","))
                    _val = string.Concat("\"", _val, "\"");

                //Replace any \r or \n special characters from a new line with a space
                if (_val.Contains("\r"))
                    _val = _val.Replace("\r", " ");
                if (_val.Contains("\n"))
                    _val = _val.Replace("\n", " ");

                _valueLine = string.Concat(_valueLine, _val, ",");

            } else {

                _valueLine = string.Concat(string.Empty, ",");
            }
        }

        _stringWriter.WriteLine(_valueLine.TrimEnd(','));
    }

    var streamWriter = new StreamWriter(stream);
        streamWriter.Write(_stringWriter.ToString());
}

We are partially done. Now, we need to make use out of this. I registered this formatter into the pipeline with the following code inside Global.asax Application_Start method:

GlobalConfiguration.Configuration.Formatters.Add(
    new CSVMediaTypeFormatter(
        new  QueryStringMapping("format", "csv", "text/csv")
    )
);

On my sample application, when you navigate to /api/cars?format=csv, it will get you a CSV file but without an extension. Go ahead and add the csv extension. Then, open it with Excel and you should see something similar to below:

image

This implementation is also on my ASP.NET Web API package (TugberkUg.Web.Http) and you can get it via Nuget:

PM> Install-Package TugberkUg.Web.Http -Pre

This package contains other stuff related to ASP.NET Web API. You can check out the source code on https://github.com/tugberkugurlu/ASPNETWebAPISamples/tree/master/TugberkUg.Web.Http/src/TugberkUg.Web.Http.

The sample I used here is also on GitHub:https://github.com/tugberkugurlu/ASPNETWebAPISamples/tree/master/TugberkUg.Web.Http/src/samples/CSVMediaTypeFormatterSample

There are some caveats, though. If your class has nested custom types, then this one does not support that. You will see that, type of the class will be printed under the particular column.

Involving Action Selection Process in ASP.NET MVC with ActionNameSelectorAttribute

We will see how we can involve action selection process in ASP.NET MVC with ActionNameSelectorAttribute with a real world use case scenario.
2012-03-21 07:14
Tugberk Ugurlu


In ASP.NET MVC, out of the box Controller class provides us a nice way to work with the framework. One of the advantages of using this class as a base controller class is that it provides so much nice functionality. One of those is ActionNameSelectorAttribute class.

This class represents an attribute that affects the selection of an action method. ActionNameAttribute class is an implementation of this abstract class and provides an ability to catch requests which comes to a particular action. Here is a sample:

public class HomeController : Controller { 

    [ActionName("FooBar")]
    public ViewResult Foo() { 
    
        return View();
    }
}

We have an action method named Foo and we know that MVC Framework will pick the method which has the same name as the action route parameter. In this case, we expect Foo method to be invoked if we hit /Home/Foo but it is not going to be because we supplied the ActionNameAttribute to involve in the action selection process and tell it to pick actions which has the FooBar value.

You might be using ASP.NET MVC for a while now and have never used this feature so far but sometimes this might come in handy. Here is a weird use case which I needed to implement:

In an application, I made use of new JavaScript pushstate and popstate features but I wanted to gracefully handle this. I implemented some sort of logic at client side and server side. Finally, I got it right but there was a problem:

I have an Index action which excepts all GET and POST requests but I wanted to invoke some other function if the request comes as POST and is an none-ajax request. there are some ways to handle this, just like checking the request method and if the request is an Ajax request but it felt so dirty to me. So, I decided to take advantage of ActionNameSelectorAttribute.

Here is the implementation:

[AttributeUsage(
    AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class NoneAjaxActionNameAttribute : ActionNameSelectorAttribute {

    public NoneAjaxActionNameAttribute(string name) {
        if (String.IsNullOrEmpty(name)) {
            throw new ArgumentException("Name paramater is null", "name");
        }

        Name = name;
    }

    public string Name {
        get;
        private set;
    }

    public override bool IsValidName(ControllerContext controllerContext, 
        string actionName, MethodInfo methodInfo) {

        return 
            String.Equals(actionName, Name, StringComparison.OrdinalIgnoreCase) &&
            !controllerContext.HttpContext.Request.IsAjaxRequest();
    }
}

As you see, it implements the ActionNameSelectorAttribute class and overrides only one method which is IsValidName. Inside that method, we should decide whether the action is in a valid state to be invoked or not. In our case, it checks the action name against the supplied name and if the request is an Ajax request or not.

Her is my controller which made use of this attribute:

public class ContentSearchController : Controller {

    private readonly IContentSearchService _contentSearchService;
    const int pageSize = 10;

    public ContentSearchController(IContentSearchService contentSearchService) {

        _contentSearchService = contentSearchService;
    }

    public ActionResult Index(string q, int page = 1) {

        var model = _contentSearchService.Search(q, page, pageSize);

        if (Request.IsAjaxRequest()) {
        
            return Json(new { 
                    data = this.RenderPartialViewToString("_SearchResult", model) 
            });
        }

        return View(
            model
        );
    }

    [NoneAjaxActionName("Index"), HttpPost]
    public RedirectToRouteResult Index_post(string searchTerm) {

        return RedirectToAction("index", new { q = searchTerm });
    }
}

As you see, I also added HttpPostAttribute to pick only POST requests.

By the help of a little bit of code, we suddenly find ourselves in the middle of action selection process and I think it is pretty powerful even if it’s a cheesy implementation.

GenericRepository.EF Version 0.2.1 Has Been Released

Entity Framework DbContext Generic Repository Implementation v0.2.1 has been released and pushed to Nuget live feed PM> Install-Package GenericRepository.EF
2012-03-07 08:32
Tugberk Ugurlu


Couple of weeks ago, I have done two blog post on Generic Repository Pattern - Entity Framework, ASP.NET MVC and Unit Testing Triangle and How to Work With Generic Repositories on ASP.NET MVC and Unit Testing Them By Mocking and I have put up the https://github.com/tugberkugurlu/GenericRepoWebApp up on GitHub as well.

Now, the Generic Repository implementation has its own project separately: https://github.com/tugberkugurlu/GenericRepository. This is a simple project and has not much inside it but it is nice to have something static so that it can be improved along the way.

I also blogged about Entity Framework DbContext Generic Repository Implementation Is Now On Nuget and GitHub and now I have just pushed the the version 0.2.1 to Nuget live feed.

@bmccord has done all the additions and I would like to thank him for that.

Here is a brief intro about this mini project:

This little project contains a Generic Repository infrastructure for .NET applications and also a DbContext Implementation of that.

You can find more information about the main idea of this pattern and the usage on ASP.NET MVC along with Unit Testing by visiting the below links:

How to Install

You can directly install this little project from Nuget. There are two packages:

GenericRepository

PM> Install-Package GenericRepository

Generic Repository Infrastructure For .NET Applications

GenericRepository.EF

PM> Install-Package GenericRepository.EF

Generic Repository DbContext Implementation

Releases

Under the master branch, you can find the latest stable release of this project.

Also, you can see the most up-to-date project under develop branch. Repository under develop branch is possibly the unstable version of the project.

You can also find all the releases under Tags section.

I await for your PRs :)

API Key Authorization Through Query String In ASP.NET Web API AuthorizationFilterAttribute

We will see how API key authorization (verification) through query string would be implemented In ASP.NET Web API AuthorizationFilterAttribute
2012-03-05 14:23
Tugberk Ugurlu


Update on the 29th of June, 2012:

The nuget package I use inside this post is not compatable with ASP.NET Web API RC and will not be with ASP.NET Web API RTM. I have another package named WebAPIDoodle which has the same funtionality as here. The source code for WebAPIDoodle: https://github.com/tugberkugurlu/WebAPIDoodle

Update on the 17th of October, 2012:

Confession

@SoyUnEmilio has pointed out a very good topic in his comment and I replied back to him but I would like to make it clear inside the post itself, too.

I wrote this article at the early stages of the framework and I now think that I mixed the concepts of authantication and authorization a lot. So, this blog post does not point you to  a good way of implementing authantication and authorization inside you ASP.NET Web API application. I don't want to delete the stuff that I don't like anymore. So, this blog post will stay as it is but I don't want to give the wrong impression as well. As the framework is now more mature, my thoughts on authentication and authorization is shaped better.

In my opinion, you should implement your authantication through a message handler and you almost always don't want to try to perform authorization inside that handler. You may only return "Unauthorized" response inside the message handler (depending on your situation) if the user is not authanticated at all but that should be futher than that. Here is a message handler sample for the API Key authentication: ApiKeyAuthenticationHandler.cs.

As for the authorization part, it can be handled by the System.Web.Http.AuthorizeAttribute. The AuthorizeAttribute checks against the Thread.CurrentPrincipal. So, the principal that you have supplided inside your message handler will be checked against. You also have a change to perform role or user name based authorization through the AuthorizeAttribute.

If you are going to build a REST API, you don’t probably want to expose all the bits and pieces to everyone. Even so, you would like to see who are making request for various reasons. One of the best ways is the API Key verification to enable that.

In a nutshell, I'll try to explain how it works. You give each user an API key (a GUID would be suitable) and ask them to concatenate this key on the request Uri as query string value. This business logic of assigning the keys works like this. But IMO, one thing is important. No matter what you do, do not manage the API key as admin. You need to find a way to make users manage their keys. User should be able to reset their API key whenever they want and by doing that, old key must gets invalid. As much as this part of the process is important, how you very them on your application is another issue.

With ASP.NET Web API, it is pretty easy to intercept a request and change the behavior of that request in any level. For API Key verification, we have two options: 1) Creating a DelegetingHandler and register it as a message handler. 2) Creating an Authorization filter which will be derived from AuthorizationFilterAttribute class. With one of those two ways, we can verify the user according to API Key supplied.

Honestly, I am not sure which one would be the best option. But, it is certain that if you don’t want the whole application to be API key verified, a filter is the best option and it can be applied to an action, controller and globally for entire application. On the other hand, message handlers are involved before the filters. So, that might seem better if you would like your whole app to be API key verified.

I have created an API key verification filter and I tried to make it generic so that it can be applied for all different verification scenarios. Let me show you what I mean.

First of all, go get the bits and pieces through Nuget. The package is TugberkUg.Web.Http and it is a prerelease package for now:

PM> Install-Package TugberkUg.Web.Http -Pre

This package contains other stuff related to ASP.NET Web API. You can check out the source code on https://github.com/tugberkugurlu/ASPNETWebAPISamples/tree/master/TugberkUg.Web.Http/src/TugberkUg.Web.Http.

For the purpose of this post, what we are interested in is ApiKeyAuthAttribute class and IApiKeyAuthorizer interface. The logic works in a very simple way:

We need a class which will be derived from IApiKeyAuthorizer interface.

public interface IApiKeyAuthorizer {

    bool IsAuthorized(string apiKey);
    bool IsAuthorized(string apiKey, string[] roles);
}

As you can see, there are two methods here. First one takes only one parameter which is the API key. This method will be invoked if you try to verify the request only based on API key. Unlike the first one, the second method takes two parameters: API key as string and roles as array of string. This one will be invoked if you try to verify the request based on API key and roles.

I have created an in memory API key authorizer to try this out:

public class InMemoryApiKeyAuthorizer : IApiKeyAuthorizer {

    private static IList<User> _validApiUsers = new List<User> { 

        new User { ApiKey = "d9c99318-53b6-4846-8613-e5aecb473066", 
            Roles = new List<Role>() { 
                new Role { Name = "Admin" } 
            }
        },
        new User { ApiKey = "dd97a5aa-704e-4c9e-9bd5-5e2828392eee", 
            Roles = new List<Role>() { 
                new Role { Name = "Customer" } 
            }
        },
        new User { ApiKey = "b2e684d7-8807-4232-b5fc-1a6e80c175c0", 
            Roles = new List<Role>() { 
                new Role { Name = "Admin" } 
            }
        },
        new User { ApiKey = "36171dc0-4925-4b12-a162-0d6d193acb75" },
        new User { ApiKey = "c8028fae-4887-4e91-8fa5-9655adae6ec1" },
        new User { ApiKey = "c4bdb227-095a-4fde-8db5-1c96d86e897a" },
        new User { ApiKey = "ff10e537-44d5-49b3-add2-6011f54de996" },
        new User { ApiKey = "3dcd18cf-e373-4436-9171-aa7f20dae23c" },
        new User { ApiKey = "17b2663d-df81-4f63-b10e-5ed918a920cf" },
        new User { ApiKey = "44fffbf2-8b32-4c4c-834a-518dd0279efa" }
    };

    public bool IsAuthorized(string apiKey) {

        return
            _validApiUsers.Any(x => x.ApiKey == apiKey);
    }

    public bool IsAuthorized(string apiKey, string[] roles) {

        if(_validApiUsers.Any(x => 
            x.ApiKey == apiKey && x.Roles.Where(r => 
                roles.Contains(r.Name)).Count() > 0)) {

            return true;
        }

        return false;
    }
}

Here, normally you would look at the supplied information about the request and return either true or false. As you can imagine, the request will be verified if true is returned. If not, then we will handle the unauthorized request in a specific way. We will get to there in a minute.

I am not sure these two parameters enough to see if the request is legitimate or not. I had a chance to easily supply the System.Web.Http.Controllers.HttpActionContext as parameter to these methods but I didn’t. Let me know what you think.

Now we have our logic implemented, we can now apply the filter to our application. As you know, filters are attributes and our attribute is as follows:

public class ApiKeyAuthAttribute : AuthorizationFilterAttribute {

    public ApiKeyAuthAttribute(string apiKeyQueryParameter, Type apiKeyAuthorizerType);

    public string Roles { get; set; }

    protected virtual void HandleUnauthorizedRequest(HttpActionContext actionContext);
    public override void OnAuthorization(HttpActionContext actionContext);
    
}

ApiKeyAuthAttribute has only one constructor and takes two parameters: apiKeyQueryParameter as string for the query string parameter name which will carry the API key and apiKeyAuthorizerType as Type which is the type of Api Key Authorizer which implements IApiKeyAuthorizer interface. We also have a public string property called Roles which accepts comma separated list of roles which user needs to be in.

The usage of the filter is simple as follows:

[ApiKeyAuth("apiKey", typeof(InMemoryApiKeyAuthorizer), Roles = "Admin")]
public class CarsController : ApiController {

    public string[] GetCars() {

        return new string[] { 
            "BMW",
            "FIAT",
            "Mercedes"
        };
    }
}

Now, when we hit the site without API Key and with the legitimate user API key which is not under the Admin role, we will get 401.0 Unauthorized response back:

apiKey

This is the default behavior when an unauthorized user sends a request but can be overridden. You need to simply override the HandleUnauthorizedRequest method and implement your own logic.

When we send a request with a proper API key, we will get the expected result:

image

The sample I used here is also on GitHub: https://github.com/tugberkugurlu/ASPNETWebAPISamples/tree/master/TugberkUg.Web.Http/src/samples/ApiKeyAuthAttributeSample

If you have any advice, please comment or fork me on GitHub.

Tags