Wednesday 8 April 2015

Configuring CORS in MVC Web Api 2

This article will describe how developers can handle the restrictions of the Same-Origin Policy that exists in all browsers today by relaxing these restrictions using CORS, Cross-origin resource sharing. Developers that have worked some with Javascript and Ajax calls, for example using jQuery, know about the limitations that are imposed on browsers for scripts to abide the "same-origin policy". If a script written in Javascript tries to access a remote resource on another host, or even another website and/or port on the same machine, chances are high that the Ajax call will although executed, not be returned to the caller (calling script). Typically if a developer checks the Developer Tools in a browser (usually F12), the following error pops up:

XMLHttpRequest cannot load http://localhost:58289/api/products/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:62741' is therefore not allowed access.

This error is because the remote resource, in this case the remote service which is another ASP.NET Web API 2 site on the same machine (localhost), does not allow this origin because of the missing 'Access-Control-Allow-Origin' header in the response. The origin itself is the requesting address and will be sent in the request as the 'Origin' header. The request in this particular case was:

Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8,nb;q=0.6,sv;q=0.4
Cache-Control:max-age=0
Connection:keep-alive
Host:localhost:58289
Origin:http://localhost:62741
Referer:http://localhost:62741/index.html
User-Agent:Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36

Note the origin request header above. I have enabled CORS on the remote site on the same machine but configured it to deny this address. First, to enable CORS in a MVC Web API 2 website/webapplication, install the following nuget package: Microsoft ASP.NET Web API 2.2 Cross-Origin Support 5.2.3

Install-Package Microsoft.AspNet.WebApi.Cors

Next up, edit the class WebApiConfig in the App_Start folder:

   public static void Register(HttpConfiguration config)
   {

            config.EnableCors(); 
            // Web API configuration and services

            // Web API routes
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
  }

The line that was added here in addition to the default setup is the line:
config.EnableCors(); 
It is possible to allow all calls to this remote site by setting up the web.config file with the following in <system.webServer><httpProtocol>:

    <customHeaders>
      <add name="Access-Control-Allow-Origin" value="*" />
    </customHeaders>

However, this will actually not always be desired as often one knows which origin that will call this remote resource (site) and it is possible to do this programatically. So for now, commenting out this line in web.config and in the following example we use the [EnableCors] attribute:

using ProductsApp.Models;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Cors;
using System.Web.Http.Description;

namespace ProductsApp.Controllers
{

    [EnableCors(origins: "http://localhost:62742", headers: "*", methods: "*")]
    public class ProductsController : ApiController
    {

        private readonly Product[] products = new Product[]{
            new Product { Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1 },
            new Product { Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M },
            new Product { Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M }
        };

        public IEnumerable<Product> GetAllProducts()
        {
            return products; 
        }

      
        public async Task<IHttpActionResult> GetProduct(int id)
        {
            Product product = await GetProductAsync(id);
            if (product == null)
            {
                return NotFound(); 
            }
            return Ok(product); 
        }

        private async Task GetProductAsync(int id)
        {
            await Task.Delay(1000); 
            var product = products.FirstOrDefault(p => p.Id == id);
            return product;
        }      

    }

}

The following CORS setup was applied to the entire Web API v2 controller, which inherits from API Controller:
[EnableCors(origins: "http://localhost:62742", headers: "*", methods: "*")]
Here, the orgins property can list up (comma-separated) the allowed origins. Wildcards can be used here. The headers and methods configure further the setup of CORS. The [EnableCors] attribute can be applied to a controller or to a method inside the Web API v2 controller for fine-grained control. It is possible to do custom policy of CORS by using instead of [EnableCors] attribute a custom class that implements the interface
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method,
                AllowMultiple = false)]
public class EnableCorsForPaidCustomersAttribute :
  Attribute, ICorsPolicyProvider
{
  public async Task GetCorsPolicyAsync(
    HttpRequestMessage request, CancellationToken cancellationToken)
  {
    var corsRequestContext = request.GetCorsRequestContext();
    var originRequested = corsRequestContext.Origin;
    if (await IsOriginFromAPaidCustomer(originRequested))
    {
      // Grant CORS request
      var policy = new CorsPolicy
      {
        AllowAnyHeader = true,
        AllowAnyMethod = true,
      };
      policy.Origins.Add(originRequested);
      return policy;
    }
    else
    {
      // Reject CORS request
      return null;
    }
  }
  private async Task IsOriginFromAPaidCustomer(
    string originRequested)
  {
    // Do database look up here to determine if origin should be allowed
    return true;
  }
}
Note here that we can do a database lookup inside the method IsOriginFromAPaidCustomer above. The class inherits from attribute, so one will use this attribute instead. We can add properties for further customization. Using a database-lookup will let us have control to which callers we allow to do a CORS call from their (Java)scripts without having to recompile, since the EnableCors attribute specifies the allowed origins hardcoded. There are further details of CORS, but this is really what is required to get successful ajax calls like the one below to work and avoiding the CORS violation.

    <script>

        $(document).ready(function () {

            var uri = 'http://localhost:58289/api/products/'; 

            $.ajax({
                url: uri,
                success: function (data) {
                    $.each(data, function (key, item) {
                        $('<li>', { text: formatItem(item) }).appendTo($('#products'));
                    });
                }
            });

            function formatItem(item) {
                return item.Name + ': $' + item.Price + ' ID: ' + item.Id;
            }

        });

    </script>

If it is desired to not use CORS (Cross Origin Resource-Sharing) for a given method or controller, use the [DisableCors] attribute. It is also possible to set up [EnableCors] with setting methods = "", i.e. no methods (HTTP Verbs) should be allowed CORS.

Saturday 14 March 2015

Resharper inspecting consistent locking of objects

Resharper has got a great inspection of your code of many different aspects, such as consistent locking of objects. An example is shown below, I have been using Resharper 9.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace InconsistentLocking
{
    class Program
    {

        private static readonly object Locker = new object();


        private static readonly List<object> fooness = new List<object>(); 

        static void Main(string[] args)
        {

            DoSomeFoo(); 

        }

        private static void DoSomeFoo()
        {
            lock (Locker)
            {
                fooness.Add("Foo");
            }

            lock (Locker)
            {
                fooness.Remove("Foo");
            }

            lock (Locker)
            {
                fooness.Add("Baze");
            }

            //Resharper warning next - The field is sometimes used inside synchronized block and sometimes without synchronization 

            fooness.Remove("Baze");

            lock (Locker)
            {
                foreach (var foo in fooness)
                {
                    Debug.WriteLine(foo.ToString());
                }
            }


        }

    }
}

The code shows a simple example of using the list called fooness. The warning shows that for the line fooness.Remove("Baze"); that one is not locking the resource, in this case a list in memory called fooness. To fix the warning, just hit Alt+Enter Resharper Shortcut and the code will surround the resource with the lock block again.

Tuesday 10 February 2015

Automatic mapping for deep object graphs in Entity Framework



Using the great code sample from DevTrends article "Stop using AutoMapper in your source code", I have adjusted the code a bit to support not only up to two layers deep object graphs, but arbitrarily deepth. The limit is a design choice which can be easily increased into deeper levels. The code will automatic generate the mapping code using Expression Trees. Example:


.New DevTrends.QueryableExtensionsExample.StudentSummary(){
    FirstName = $src.FirstName,
    LastName = $src.LastName,
    TutorName = ($src.Tutor).Name,
    TutorAddressStreet = (($src.Tutor).Address).Street,
    TutorAddressMailboxNumber = ((($src.Tutor).Address).Mailbox).Number,
    CoursesCount = ($src.Courses).Count
}


Consider the automatic mapping of an entity in Entity Framework to a flattened model, where the entity is a relatively deep object graph. The tedious mapping code will be boring to write when the number properties grow. If we stick to a convention where we use CamelCasing to denote levels in the object graph, we can address the subproperties arbitrarily deep with this code.

   public class StudentSummary
    {

        public string FirstName { get; set; }

        public string LastName { get; set; }

        public string NotADatabaseColumn { get; set; }

        public string TutorName { get; set; }

        public string TutorAddressStreet { get; set;  }

        public string TutorAddressMailboxNumber { get; set; }

        public int CoursesCount { get; set; }

        public string FullName
        {
            get { return string.Format("{0} {1}", FirstName, LastName); }
        }

    }

Note here that for a given property such as TutorAddressMailboxNumber, the code will look for the property Tutor.Address.Mailbox.Number since the CamelCasing convention used here will check this. The implementation of the Project() method and the To() method on IQueryable<T> is shown next. The code uses Expression Trees to generate the required automatic mapping code. Note that the method Buildbinding method will run when the Expression.Lambda statement is executed, when debugging.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text.RegularExpressions;

namespace DevTrends.QueryableExtensionsExample
{

    public static class QueryableExtensions
    {
        public static ProjectionExpression<TSource> Project<TSource>(this IQueryable<TSource> source)
        {
            return new ProjectionExpression<TSource>(source);
        }
    }

    public class ProjectionExpression<TSource>
    {
        private static readonly Dictionary<string, Expression> _expressionCache = new Dictionary<string, Expression>();

        private readonly IQueryable<TSource> _source;

        public ProjectionExpression(IQueryable<TSource> source)
        {
            _source = source;
        }

        public IQueryable<TDest> To<TDest>()
        {
          var queryExpression = GetCachedExpression<TDest>() ?? BuildExpression<TDest>();

            return _source.Select(queryExpression);
        }        

        private static Expression<Func<TSource, TDest>> GetCachedExpression<TDest>()
        {
            var key = GetCacheKey<TDest>();

            return _expressionCache.ContainsKey(key) ? _expressionCache[key] as Expression<Func<TSource, TDest>> : null;
        }

        private static Expression<Func<TSource, TDest>> BuildExpression<TDest>()
        {
            var sourceProperties = typeof(TSource).GetProperties();
            var destinationProperties = typeof(TDest).GetProperties().Where(dest => dest.CanWrite);
            var parameterExpression = Expression.Parameter(typeof(TSource), "src");
            
            var bindings = destinationProperties
                                .Select(destinationProperty => BuildBinding(parameterExpression, destinationProperty, sourceProperties))
                                .Where(binding => binding != null);

            var expression = Expression.Lambda<Func<TSource, TDest>>(Expression.MemberInit(Expression.New(typeof(TDest)), bindings), parameterExpression);

            var key = GetCacheKey<TDest>();

            _expressionCache.Add(key, expression);

            return expression;
        }        

        private static MemberAssignment BuildBinding(Expression parameterExpression, MemberInfo destinationProperty, IEnumerable<PropertyInfo> sourceProperties)
        {
            var sourceProperty = sourceProperties.FirstOrDefault(src => src.Name == destinationProperty.Name);

            if (sourceProperty != null)
            {
                return Expression.Bind(destinationProperty, Expression.Property(parameterExpression, sourceProperty));
            }

            var propertyNameComponents = SplitCamelCase(destinationProperty.Name);

            if (propertyNameComponents.Length >= 2)
            {
                sourceProperty = sourceProperties.FirstOrDefault(src => src.Name == propertyNameComponents[0]);
                if (sourceProperty == null)
                    return null; 

                var propertyPath = new List<PropertyInfo> { sourceProperty };
                TraversePropertyPath(propertyPath, propertyNameComponents, sourceProperty);

                if (propertyPath.Count != propertyNameComponents.Length)
                    return null; //must be able to identify the path 

                 MemberExpression compoundExpression = null;
                
                for (int i = 0; i < propertyPath.Count; i++)
                {
                    compoundExpression = i == 0 ? Expression.Property(parameterExpression, propertyPath[0]) : 
                        Expression.Property(compoundExpression, propertyPath[i]); 
                }

                return compoundExpression != null ? Expression.Bind(destinationProperty, compoundExpression) : null; 
            }

            return null;
        }

        private static List<PropertyInfo> TraversePropertyPath(List<PropertyInfo> propertyPath, string[] propertyNames, 
            PropertyInfo currentPropertyInfo, int currentDepth = 1)
        {
            if (currentDepth >= propertyNames.Count() || currentPropertyInfo == null)
                return propertyPath; //do not go deeper into the object graph

            PropertyInfo subPropertyInfo = currentPropertyInfo.PropertyType.GetProperties().FirstOrDefault(src => src.Name == propertyNames[currentDepth]); 
            if (subPropertyInfo == null)
                return null; //The property to look for was not found at a given depth 

            propertyPath.Add(subPropertyInfo);

            return TraversePropertyPath(propertyPath, propertyNames, subPropertyInfo, ++currentDepth);
        }

        private static string GetCacheKey<TDest>()
        {
            return string.Concat(typeof(TSource).FullName, typeof(TDest).FullName);
        }

        private static string[] SplitCamelCase(string input)
        {
            return Regex.Replace(input, "([A-Z])", " $1", RegexOptions.Compiled).Trim().Split(' ');
        }

    }    
}

The database is initialized with some sample data, the sample uses an Entity Framework CodeFirst database.

using System;
using System.Data.Entity;
using System.Linq;

namespace DevTrends.QueryableExtensionsExample
{
    class Program
    {
        static void Main()
        {
            Database.SetInitializer(new TestDataContextInitializer());

            using (var context = new StudentContext())
            {
                ExampleOne(context);

                ExampleTwo(context);                
            }

            Console.Write("\nPress a key to exit: ");
            Console.Read();
        }

        private static void ExampleOne(StudentContext context)
        {
            // This is the kind of projection code that we are replacing

            //var students = from s in context.Students
            //               select new StudentSummary
            //                          {
            //                              FirstName = s.FirstName,
            //                              LastName = s.LastName,
            //                              TutorName = s.Tutor.Name,
            //                              CoursesCount = s.Courses.Count
            //                          };


            // The line below performs exactly the same query as the code above.

            var students = context.Students.Project().To();

            Console.Write("Example One\n\n");

            // Uncomment this to see the generated SQL. The extension method produces the same SQL as the projection.
            //Console.WriteLine("SQL: \n\n{0}\n\n", students);

            foreach (var student in students)
            {
                Console.WriteLine("{0} is tutored by {1} in {2} subject(s).", student.FullName, student.TutorName, student.CoursesCount);
            }
        }

        private static void ExampleTwo(StudentContext context)
        {
            //var students = from s in context.Students
            //               select new AnotherStudentSummary()
            //               {
            //                   FirstName = s.FirstName,
            //                   LastName = s.LastName,
            //                   Courses = s.Courses
            //               };

            var students = context.Students.Project().To();

            Console.WriteLine("\nExample Two\n");
            
            //Console.WriteLine("SQL: \n\n{0}\n\n", students);

            foreach (var student in students)
            {
                var coursesString = string.Join(", ", student.Courses.Select(s => s.Description).ToArray());
                Console.WriteLine("{0} {1} takes the following courses: {2}", student.FirstName, student.LastName, coursesString);
            }
        }
    }        
}



using System;
using System.Data.Entity;
using System.Linq;

namespace DevTrends.QueryableExtensionsExample
{
    class Program
    {
        static void Main()
        {
            Database.SetInitializer(new TestDataContextInitializer());

            using (var context = new StudentContext())
            {
                ExampleOne(context);

                ExampleTwo(context);                
            }

            Console.Write("\nPress a key to exit: ");
            Console.Read();
        }

        private static void ExampleOne(StudentContext context)
        {
            // This is the kind of projection code that we are replacing

            //var students = from s in context.Students
            //               select new StudentSummary
            //                          {
            //                              FirstName = s.FirstName,
            //                              LastName = s.LastName,
            //                              TutorName = s.Tutor.Name,
            //                              CoursesCount = s.Courses.Count
            //                          };


            // The line below performs exactly the same query as the code above.

            var students = context.Students.Project().To<StudentSummary>();

            Console.Write("Example One\n\n");

            // Uncomment this to see the generated SQL. The extension method produces the same SQL as the projection.
            //Console.WriteLine("SQL: \n\n{0}\n\n", students);

            foreach (var student in students)
            {
                Console.WriteLine("{0} is tutored by {1} in {2} subject(s).", student.FullName, student.TutorName, student.CoursesCount);
            }
        }

        private static void ExampleTwo(StudentContext context)
        {
            //var students = from s in context.Students
            //               select new AnotherStudentSummary()
            //               {
            //                   FirstName = s.FirstName,
            //                   LastName = s.LastName,
            //                   Courses = s.Courses
            //               };

            var students = context.Students.Project().To<AnotherStudentSummary>();

            Console.WriteLine("\nExample Two\n");
            
            //Console.WriteLine("SQL: \n\n{0}\n\n", students);

            foreach (var student in students)
            {
                var coursesString = string.Join(", ", student.Courses.Select(s => s.Description).ToArray());
                Console.WriteLine("{0} {1} takes the following courses: {2}", student.FirstName, student.LastName, coursesString);
            }
        }
    }        
}


I have tested the code with a depth of four for the object graph, which will be sufficient in most cases. The maximum level is 10 just to prevent the recursion for giving a possible stack overflow, but the limit can be easily adjusted here. Using the code provided here, it will be easier to automatic map entity framework code into models. The code provided here should be used for retrieving data, such as selects. Note that we are short-circuiting the change tracking of Entity Framework here and must stick to a CamelCasing convention to get the automatic mapping from Entity to the flattened model, that must keep to the CamelCasing convention. .

Download the sample code here

Source code in Visual Studio 2012 solution

Example integration test (The ObjectContextManager.ScopedOpPlanDataContext object here is an example ObjectContext)


        [Test]
        [Category(TestCategories.IntegrationTest)]
        public void ProjectToPerformsExpected()
        {
            using (var context = ObjectContextManager.ScopedOpPlanDataContext)
            {
                var globalParameters = context.GlobalParameters.Project().To<GlobalParametersDataContract>().ToList();
                Assert.IsNotNull(globalParameters);
                CollectionAssert.IsNotEmpty(globalParameters);
            }
        }