16 Sep

Burned by Ternary Operators

First let me say that I’m not a fan of ternary operators.  I try to avoid them because I feel that an explicit if/else is much more readable.  I do use them on occasion and this seemed like the perfect place for them.

I ran into a interesting problem while trying to get a Linq where clause to work with ternary operators.  In hindsight the problem is pretty obvious, but it stumped me and one of my coworkers for a few minutes.  It wasn’t until we solved the problem in a different way that I realized what I had initially missed.

First the setup:

var books = new List<Book>();
books.Add(new Book { Title = "To Kill a Mockingbird", Description = null });
books.Add(new Book { Title = "Catcher in the Rye", Description = null });

There where clause I was building was part of some basic search functionality.  It would take a passed in value and check to see if the Title or the Description contained that value:

var qry = books.Where(u =>
            u.Description == null ? false : u.Description.ToUpper().Contains(searchStr)
            || u.Title == null ? false : u.Title.ToUpper().Contains(searchStr)
            );

Attempts to search for the letter T were returning no results.  Like I said, I struggled with it, called in a second set of eyes and they couldn’t see the problem.  We then re-wrote where clause like this:

var qry = books.Where(u =>
            (u.Description != null && u.Description.ToUpper().Contains(searchStr))
            || (u.Title != null && u.Title.ToUpper().Contains(searchStr))
            );

This returned 2 results as expected.  After a bit of rumination I realized the problem was my lack of parentheses.  I thought I had written this:

var qry = books.Where(u =>
            (u.Description == null ? false : u.Description.ToUpper().Contains(searchStr))
            || (u.Title == null ? false : u.Title.ToUpper().Contains(searchStr))
            );

When I had essentially written this:

var qry = books.Where(u =>
            u.Description == null ? false : 
                    (
                    u.Description.ToUpper().Contains(searchStr)
                    || u.Title == null ? false : u.Title.ToUpper().Contains(searchStr)
                    )
            );

This was clearly just my misunderstanding of how ternary operators are interpreted, and I’m unlikely to ever forget this, but I’m also going to continue to avoid ternary operators wherever I can and encourage others to do the same.

10 Sep

Repository Pattern with Entity Framework

I’m currently working on a little side project using ASP.Net MVC and Entity Framework, so of course my urls looks something like http://mysite.com/orders/14 to pull up the order that has OrderId 14.  The problem of course is security, I need to ensure that users can only view their own orders.

My first pass at managing this was to just add the UserId to the where clause of a LINQ query.

dbContext.Orders.FirstOrDefault(x => x.Id == OrderId && x.UserId == userId);

This obviously works, but leaves me open making mistakes down the road by either forgetting to add that to the where clause, or on a more complex where clause having the UserId portion not working in one of the Or branches.  My first thought was of course to add some unit tests to the controller actions to account for this, but when I thought about doing that I realized I would essentially be writing the same test for every action.

I decided I needed to move the responsibility for adding the UserId to the where clause to a central location that handled that for all calls to user specific entities.  I could then write unit tests that code once and rest assured that all my controller actions were covered for that case.

My solution involved putting a generic repository layer on top of Entity Framework that was able to both.

First I defined the repository interface:

public interface IRepository<T>
{
    T GetById(int id);
    IQueryable<T> GetAll();
    void Add(T entity);
    void Update(T entity);
    void Delete(int id);
    void Delete(T entity);
}

And an interface that all user specific entities must implement

public interface IUserEntity
{
    int Id { get; set; } 
    int UserId { get; set; }
}

Then the repository itself with methods for all CRUD operations.  You’ll notice that each operation checks to ensure that the UserId of the entity affected matches the UserId that was used to create the repository:

public class UserRepository<T> : IRepository<T> where T : class, IUserEntity
{
    private readonly int _userId;

    public UserRepository(DbContext dbContext, int userId)
    {
        _userId = userId;
        if (dbContext == null)
        {
            throw new ArgumentNullException("dbContext");
        }
        DbContext = dbContext;
        DbSet = DbContext.Set<T>();
    }

    protected DbContext DbContext { get; set; }

    protected DbSet<T> DbSet { get; set; }

    public virtual IQueryable<T> GetAll()
    {
        return DbSet.Where(x => x.UserId == _userId);
    }

    public virtual T GetById(int id)
    {
        var entity = DbSet.FirstOrDefault(x => x.Id == id && x.UserId == _userId);
        return entity;
    }

    public virtual void Add(T entity)
    {
        entity.UserId = _userId;
        DbEntityEntry dbEntityEntry = DbContext.Entry(entity);
        if (dbEntityEntry.State != EntityState.Detached)
        {
            dbEntityEntry.State = EntityState.Added;
        }
        else
        {
            DbSet.Add(entity);
        }
    }

    public virtual void Update(T entity)
    {
        if (entity.UserId != _userId)
        {
            return;
        }

        DbEntityEntry dbEntityEntry = DbContext.Entry(entity);
        if (dbEntityEntry.State == EntityState.Detached)
        {
            DbSet.Attach(entity);
        }
        dbEntityEntry.State = EntityState.Modified;
    }

    public virtual void Delete(T entity)
    {
        if (entity.UserId != _userId)
        {
            return;
        }

        DbEntityEntry dbEntityEntry = DbContext.Entry(entity);
        if (dbEntityEntry.State != EntityState.Deleted)
        {
            dbEntityEntry.State = EntityState.Deleted;
        }
        else
        {
            DbSet.Attach(entity);
            DbSet.Remove(entity);
        }
    }

    public virtual void Delete(int id)
    {
        var entity = GetById(id);
        if (entity == null) return; // not found; assume already deleted.

        if (entity.UserId != _userId)
        {
            return;
        }

        Delete(entity);
    }
}

Next we wrap all of those repositories up in a Unit of Work pattern, (sample code only shows one repository, my production code has all my repositories in one UOW class).

public class UoW : IDisposable
{
    private readonly int _userId;
    private MyDbContext DbContext { get; set; }

    public UoW(int userId)
    {
        _userId = userId;
        DbContext = new MyDbContext();
    }

    private IRepository<Order> _orders;
    public IRepository<Order> Orders
    {
        get
        {
            if (_orders == null)
            {
                _orders = new UserRepository<Order>(DbContext, _userId);
            }
            return _orders;
        }
    }

    public void Dispose()
    {
        if (DbContext != null)
        {
            DbContext.Dispose();
        }
    }
}

Now when we want all of the Order 14, we create an instance of the Unit Of Work class for the current user and request Order 14.

var uow = new UoW(123);
uow.Orders.GetById(14);

And if someone types http://mysite.com/orders/14 into the address bar, they won’t get back any data if their UserId doesn’t match the UserId for Order 14.

It’s still not very testable, but all it takes is adding another constructor to allow us to pass in the DBContext:

    public UoW(int userId, MyDbContext dbContext)
    {
        _userId = userId;
        DbContext = dbContext;
    }

Now we can use any DBContext we like for testing.  I’m using Effort – Entity Framework Unit Testing Tool to create an in memory database context for testing purposes.  It’s fast and simple to use.

04 Jun

WP7 Application Capabilities

WMPoserUser posted some interesting stats on what capabilities applications are requesting.  Interesting stuff, but they clearly haven’t published an app, or at least not an ad supported app.

First let me say that I have only published a single app so far, so I’m not some amazing expert.  My app, Chess Tactics, doesn’t actually need any capabilities by itself.  That being said I have quite a few capabilities listed.  Most of these capabilities are required by Microsoft’s ad control, with one additional capability required by MTIKS (a utility I’m using usage and error detail).

Here’s my capabilities list and why I include it and why I think it’s required:

  • Phone Dialer
    • MS Ad Control – so you can dial a phone number direct from an advertisement
  • Networking
    • MS Ad Control – to download ads for display and report any clicks
    • MTIKS – Send data back for reporting
  • Web Browser
    • MS Ad Control – to display the ads
  • User Identity
    • MS Ad Control – to track what the users interests are across apps
    • MTIKS – Track user loyalty across app versions and user device upgrades
  • Media Library
    • MS Ad Control – No idea at all
  • Device Identity
    • MTIKS – To track what devices are using my app in case a particular one become problematic

None of these capabilities indicate an app is trying to do anything nefarious.  I would expect pretty much every app to need these capabilities.  Now if an app wants access to my microphone, it better have a damned good reason.

Between collecting stats, serving ads, and apps that use network service to provide value, I think it’s out of line to say that 95% requesting network services is “larger than necessary”.  In fact, it makes me wonder what the 5% of apps that don’t require network access are.

If you know why the MS ad control needs access to the Media Library please let me know in the comments.

24 May

T4 Generated Wrapper for a WCF Client

Background

The idea for this article came from two places:

I’m writing an application that gets all of its data from a WCF service. Each time I call the WCF service, I end up having to write a bunch of duplicate code and of course I don’t like to type, so I was trying to find a way to not have to write that code.
The app I’m developing is an internal business application, and we release weekly. Each release to the WCF services could be incompatible with the previous client. That means that I need to do the release during off hours. I don’t like working nights, so I wanted to find a way to have multiple copies of the service running and have the client choose which service to access based on its version, but I didn’t want to have to keep changing the config file for the client with each release.
First I’ll solve those two problems, and then I’ll demonstrate how to use T4 to generate this wrapper from the WCF service reference.

Prerequisites

To run the code, you’ll need to download and install the T4Toolbox.

Problem #1

A typical WCF call looks like this:

var proxy = new WCFServiceWrapper.WcfSvc.Service1Client()
try
{
    returnValue = proxy.GetData(value);
    proxy.Close();
}
catch
{
    proxy.Abort();
    throw;
}
Proxy = null;

To keep from having to write all that code every time I make a call to the WCF service, I created a static class that has a static method with the same signature as the WCF method I’m calling.

public static partial class SvcWrapper
{   
    public static string GetData(int value)
    {
        var proxy = GetServiceClient()
        try
        {
            var returnValue = proxy.GetData(value);
            proxy.Close();
            return returnValue;
        }
        catch
        {
            proxy.Abort();
            throw;
        }
    }
}

Now that same call that took 12 lines of code is now just this one line:

returnValue = SvcWrapper.GetData(value); 

Problem #2

To solve the second problem, I just added another method that creates an instance of the service client for me.

public partial class SvcWrapper
{
    private static string _serviceAddress;
    private static string _configName;
    private static bool _needsConfig = true;
    internal static WcfSvc.Service1Client GetServiceClient()
    {
        if (_needsConfig)
        {
            //At this point I'd do some hoopajoop to determine what the
            //current service address is for this version
            //something like:
  
            //ServiceConfig config = SomeWCFService.GetServiceConfig(versionNo);
            //_serviceAddress = config.Address;
            //_configName = config.ClientEndPointName;
            //The address of the service endpoint
            _serviceAddress = "http://localhost:50324/Service1.svc"

            //This string is the Name of the Client Endpoint
            //as defined in the running EXE's app.config
            _configName = "WSHttpBinding_IService1";
        }
        return new WCFServiceWrapper.WcfSvc.Service1Client(_configName, _serviceAddress);
    }
}

There’s nothing earth shattering about that code, and I haven’t even implemented the look of the address and config yet, but the shell is there for me to finish at a later date. But now if I want to add another endpoint configuration to the app.config file for this service, I can do that and have only one place to change which endpoint the app uses.

Using T4 to Generate Wrapper Methods

Now, I’ve solved my original 2 problems, but I’ve created another one. I’m going to have to create and maintain a wrapper method for every method exposed by the WCF Service. This is the perfect opportunity to do a little code generation with T4.

First thing you need to do is add references to the EnvDTE and T4ToolBox. Then add a new text file called GenerateServiceWrapper.t4. This file holds the code that is not specific to the service we’re wrapping, and the t4 extension doesn’t create the child .cs file that the .tt extension creates.

This file has 5 methods:

GetServiceInterface – takes the name of the service and searches the project for a file that matches. Then it calls FindInterface.
FindInterface – takes a project item and searches it for an interface. It returns the first one it finds, and nullif it doesn’t find one. It could maybe use some error handling but…
GetMethodSignature – this takes one of the public methods found on the interface and returns a string that will be the method signature of the wrapper method.
GetMethodCall – this takes one of the public methods found on the interface and returns a string that will be the call to that method on the WCF Service.
GetServiceWrapper – is where the rubber meets the road. This calls GetServiceInterface to get the interface, loops through the public methods and generates the wrapper methods.
Here’s the contents of that file, you’ll need to get a third-party plugin to get syntax highlighting in Visual Studio.

&lt;#@ Template Language="C#" #&gt;
&lt;#@ import namespace="EnvDTE" #&gt;
&lt;#@ include File="T4Toolbox.tt" #&gt;
&lt;#+
public void GetServiceWrapper(string LocalServiceName)
{
    EnvDTE.CodeInterface svcInterface =
    GetServiceInterface(LocalServiceName + @"\reference.cs");
    foreach (var ce in svcInterface.Members)
    {
        var meth = ce as CodeFunction;
        if (meth != null)
        {
            if (meth.Access == vsCMAccess.vsCMAccessPublic)
            {
                string methodSignature = GetMethodSignature(meth);
                string methodCall = GetMethodCall(meth);
                bool returnsVoid = false;
                if (meth.Type.AsString.Equals("void"))
                {
                    returnsVoid = true;
                }
                #&gt;
        &lt;#=methodSignature #&gt;
        {
            var proxy = GetServiceClient();
            try
            {
            &lt;#+
                if (returnsVoid)
                {
                       #&gt;    proxy.&lt;#=methodCall #&gt;;
                            proxy.Close();
            &lt;#+
                }
                else
                {
            #&gt;    var returnValue = proxy.&lt;#=methodCall #&gt;;
                proxy.Close();
                return returnValue;
&lt;#+
                }
#&gt;
            }
            catch
            {
                proxy.Abort();
                throw;
            }
        }
         
&lt;#+
            }
        }
    }
}
 
public EnvDTE.CodeInterface GetServiceInterface(string interfaceFile)
{
    ProjectItem projectItem = TransformationContext.FindProjectItem(interfaceFile);
    FileCodeModel codeModel = projectItem.FileCodeModel;
    return FindInterface(codeModel.CodeElements);
}
 
public CodeInterface FindInterface(CodeElements elements)
{
    foreach (CodeElement element in elements)
    {
        CodeInterface myInterface = element as CodeInterface;
        if (myInterface != null)
            return myInterface;
        myInterface = FindInterface(element.Children);
        if (myInterface != null)
            return myInterface;
    }
    return null;
}
 
public string GetMethodSignature(CodeFunction method)
{
    var methodSignature = new System.Text.StringBuilder();
    methodSignature.Append("public static ");
    methodSignature.Append(method.Type.AsString);
    methodSignature.Append(" ");
    methodSignature.Append(method.Name);
    methodSignature.Append("(");

    bool isFirstParameter = true;

    foreach (var prm in method.Parameters)
    {
        CodeParameter p = prm as CodeParameter;
        if (!isFirstParameter)
        {
            methodSignature.Append(", ");
        }
        else
        {
            isFirstParameter = false;
        }

        methodSignature.Append(p.Type.AsString);
        methodSignature.Append(" ");
        methodSignature.Append(p.Name);
    }

    methodSignature.Append(")");

    return methodSignature.ToString();
}
 
public string GetMethodCall(CodeFunction method)
{
    var methodCall = new System.Text.StringBuilder();
    methodCall.Append(method.Name);
    methodCall.Append("(");

    bool isFirstParameter = true;

    foreach (var prm in method.Parameters)
    {
        CodeParameter p = prm as CodeParameter;

        if (!isFirstParameter)
        {
            methodCall.Append(", ");
        }
        else
        {
            isFirstParameter = false;
        }
        methodCall.Append(p.Name);
    }
    methodCall.Append(")");
    return methodCall.ToString();
}      
#&gt;

Lastly create a text file named ServiceWrapper.tt, or something less generic as this will define the actual wrapper for the WCF Service.

It contains a link to our GenerateServiceWrapper.t4 file, the definition of our class, and a call to GetServiceWrapper to which we pass the name of the WCF Service Reference.

&lt;#@ template language="C#v3.5" hostspecific="True" #&gt;
&lt;#@ include File="T4Templates\GenerateServiceWrapper.t4" #&gt;
using System;
 
namespace WCFServiceWrapper
{
    public static partial class SvcWrapper
    {   
&lt;#      GetServiceWrapper("WcfSvc");#&gt;
    }
}

Once you save, it should generate a SvcWrapper.cs file with static methods to wrap all of your calls. Now if I want to do something like add logging to each WCF call, all I have to do is add that code to the GetServiceWrapper method in the GenerateService.t4 file, poof all my methods WCF calls are logged.

Notice that I created this class as a partial class, this allows us to put the GetServiceClient method in the same class, but in a separate file. We could have either created that method in a completely separate class, or within the ServiceWrapper.tt file. You never want to edit the generated file, as those edits will be overwritten.

Points of Interest

Syntax highlight for T4 requires a 3rd party plugin. I’ve tried a few, and they are all pretty weak.

You can’t step through T4 code (or I haven’t figured out how), so it can take some serious guess and check to figure out what’s going wrong when something goes wrong. The output window is your friend.

30 Apr

401 Unauthorized error on MERGE operations IIS 7 with WCF Data Service

I was getting this error when using WCF Data Services and trying to save an update to an object.  After quite a bit of googling, I found a work around that I didn’t like.  Allow the users write access to the .svc file.

I have a hard time believing that anyone would accept “allow the user write access to the file” as an answer in web situation.  In my case I was able to use that as a temporary fix because the website in question was internal and behind a firewall, but I knew there had to be a better answer.

UsePostTunneling

Post tunneling allows you to use your REST service with just the Post and Get verbs, and puts a little something extra in the header so that the service knows to treat the Post as a Merge, Put or Delete verb.  For WCF Data Services, all you need to do is set the UsePostTunneling property on the Context to true.

Here’s sample code from anonymized from my dataservice factory:

public static MyDataSvc.MyDataEntities GetDataSvc()
{
    Uri SvcUri = new Uri(string.Format("http://myserver.com/", "dataservice.svc"));
    var context = new MyDataSvc.MyDataEntities (SvcUri);
    context.UsePostTunneling = true;
    return context;
}