About Us

2013 Nebraska Code Camp and My Windows 8 MVVM Talk

by Mike Douglas 19. March 2013 13:31

The 3rd Annual Nebraska Code Camp was another huge success.  The conference again had top notch speakers from around the country including the keynote speaker, Ted Neward.  Deliveron Consulting Services had the honor of being a sponsor for the second year in a row.  Thanks to everyone that stopped by our booth and came to my talk.  It was great seeing familiar faces and meeting a lot of new people.  I’m looking forward to going back again next year.

My talk was Developing a Windows 8 C#/XAML MVVM Application.  I had a lot of fun giving this talk.  I have been learning how to build a Windows 8 Store app for the past 3 months building an application that using TFS 2012 and Windows Azure Mobile Services.  I am hoping to publish to the app store in the next week.  I enjoyed sharing what I have learned so far and explain what is next.  I have the slides and sample code from my talk shared on my SkyDrive.  Feel free to contact me with any questions.  My contact information is in the slide deck.

Serializing ModelState errors in a json call

by Travis Ellis 4. February 2013 01:31

In ASP.net MVC, the ModelStateDictionary class contains all of the validation errors for your models that get posted from your forms. The HTML helpers Html.ValidationSummary and Html.ValidationMessageFor will look at the Model State to display these validation messages. When you are submitting your form with an AJAX request and return a JSON response, then you need to have a way to return these validation errors to your views. Here is a helpful extension method that will allow you to do that:

public static class ModelStateExtensions
{
    public static IDictionary ToSerializedDictionary(this ModelStateDictionary modelState)
    {
        return modelState.ToDictionary(
            k => k.Key,
            v => v.Value.Errors.Select(x => x.ErrorMessage).ToArray()
        );
    }
}

Now in your controller action you can return this data back to your view:

[HttpPost]
public ActionResult Create(ProjectModel model)
{
    // Validation Errors
    if(!ModelState.IsValid)
    {
        return Json(ModelState.ToSerializedDictionary());
    }

    // Success - Save Project data
}
}

In your view you can now write some javascript code to display the errors in your view.

Injecting a dependency into an action filter using ninject

by Travis Ellis 20. November 2012 04:06

One of the most powerful features of using Inversion of Control/Dependency Injection is the ability to have highly testable code. When your dependencies are interfaces instead of concrete classes, it makes it very easy for a unit test to mock that dependency:

public class ProductsController : Controller
{
    protected readonly IProductService productService;
 
    public ProductsController(IProductService productService)
    {
        this.productService = productService;
    }

    [HttpPost]
    public ActionResult GetProducts()
    {
        return Json(productService.GetAllProducts());
    }
}

The above example shows an MVC controller that takes a single dependency: IProductService. There is a single action method that is using the service to get a list of products, which is being returned via JSON. Since the dependency is defined as an interface, the code is very easy to test with a mocking framework.

What happens when you want to apply the same concept to an Action Filter? Action Filters are attributes that are added to your controllers and actions at compile time so you can’t pass a dependency through the constructor. Well, with Ninject you can.

Using NuGet, install the Ninject.MVC3 package (also works in MVC 4). This will add both the Ninject and Ninject MVC packages and add a file  called NinjectWebCommon.cs to the App_Start folder in your solution. This is where we will set up the dependency injection for our action filters. Before we can do that we will need to create our action filter.

For this example we will create a simple filter that could be used for logging. The first thing you need to do is create a dummy attribute that you can apply to your action methods:

public enum SeverityLevel
{
    Warning,
    Information
}

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)]
public class LogAttribute : FilterAttribute
{
    public LogLevel Level { get; set; }

    public LogAttribute(LogLevel level)
    {
        this.Level = level;
    }
}

This can be applied to your action methods as follows:

[Log(SeverityLevel.Information)]
public Actionresult Index()
{
    return View();
}

This attribute by itself does nothing, but it will be used as a hook to inject a dependency into our real filter:

public class LogFilter : IActionFilter
{
    protected readonly ILogService logService;
    protected readonly LogLevel level;

    public LogFilter(ILogService logService, LogLevel level)
    {
        this.logService = logService;
        this.level = level;
    }

    public void OnActionExecuted(ActionExecutedContext filterContext
    {
        // implement logging logic here
        this.logService.Log(...);
    }

    public void OnActionExecuting(ActionExecutingContext filterContext)
    {
        // implement logging logic here
        this.logService.Log(...);
    }
}

You can now write unit tests against the filter class and mock up your dependency using a mocking framework, but there is one more thing we need to do to wire everything that is up. Right now our filter has no direct tie to our attribute. Let’s change that by adding the following code to the NinjectWebCommon class in the RegisterServices method:

private static void RegisterServices(IKernel kernel)
{
    kernel.BindFilter<LogFilter>(FilterScope.Action, 0)
        .WhenActionMethodHas<LogAttribute>()
        .WithConstructorArgumentFromActionAttribute<LogAttribute>("level", attr => attr.Level);
}

The BindFilter is is an extension method that exists in the Ninject.Web.Mvc.FilterBindingSyntax namespace. Once you add this line whenever Ninject creates an action method that has the LogAttribute applied to it, it will automatically apply the LogFilter and inject any dependencies that it knows how to create. That is all you need to get dependency injection working on an MVC action filter.

Table Valued Parameters with Entity Framework

by Travis Ellis 16. November 2011 12:00

I recently worked on a project where I was calling a WCF service that returned a collection of values that had a Name and a Type. I needed to use that list to select values from another database using Entity Framework.  A typical result set from the WCF service looked like this:

var list = new List<NameAndType>
{
    new NameAndType { Name = "ABC", Type = "123" },
    new NameAndType { Name = "ABC", Type = "456" },
    new NameAndType { Name = "DEF", Type = "123" },
    new NameAndType { Name = "DEF", Type = "123" }
};

In a local database I had a table that had a composite primary key made up of Name and Type. I needed to write a query that took this list of name/type values and found matching rows in my database. This would be a simple thing to do if I had a single value as my key. If that were the case I could have written a query like this:

var list = List<string>
{
    "ABC",
    "DEF"
};
    
var items = from i in context.Items
            where list.Contains(i.Name)
            select i;

The above query will translate into a statement similar to SELECT * FROM Items WHERE Name IN ('ABC', 'DEF'). The problem is that I had two properties that I needed to predicate on. I wasn't sure how to write the query in Entity Framework but my first thought was something like the following:

var list = new List
{
    new NameAndType { Name = "ABC", Type = "123" },
    new NameAndType { Name = "ABC", Type = "456" },
    new NameAndType { Name = "DEF", Type = "123" },
    new NameAndType { Name = "DEF", Type = "123" }
};

var result = from a in context.Items
             join b in list
             on new { a.Name, a.Type } equals new { b.Name, b.Type }
             select a; 

This query threw an error complaining that only primitive types could be used. I tried a few more queries but I could not figure out a way to do this. I started to think about how I would actually accomplish this in SQL using a stored procedure and settled on using a Table-Valued Parameter (which I have blogged about before). At first I thought I was going to need to write a stored procedure and call that from Entity Framework, but after doing a little testing I was able to come up with a solution that allowed me to do this using an Entity Framework query:

DataTable dt = new DataTable();
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("Type"< typeof(string));

list.ForEach(l => dt.Rows.Add(l.Name, l.Type));

SqlParameter tableParameter = new SqlParameter("@Ids", SqlDbType.Structured);
tableParameter.TypeName = "dbo.NameAndType";
tableParameter.Value = dt;

var items = context.Database.SqlQuery<Item>(
    "SELECT * FROM dbo.Items items " +
    "INNER JOIN @Ids ids ON items.Name = ids.Name " +
    "AND items.Type = ids.Type", tableParameter);

The code creates a DataTable and adds a row for each item in my list of NameAndType values. It then creates a SqlParameter with SqlDbType of Structured and gives it a TypeName of dbo.NameAndType and a value of the table. I then created an Entity Framework query using the Database.SqlQuery<T> method which allows you to execute some SQL code. I select from my table and join to my table valued parameter and was able to get the items from my database.

One thing to note with this approach is that all of the items returned from the query will not be tracked by Entity Framework. If you need Entity Framework to track the entities you would have to do something similar to this:

foreach ( var item in items ) {
    db.Items.Attach(item);
}

In Summary

This concludes my post on writing an Entity Framework query that uses a table-valued parameter. If you have any questions, feel free to contact me with any questions.

SEO Friendly Routes with ASP.net MVC 3

by Travis Ellis 14. March 2011 16:35

One of the most important things for a modern day website is for it to be easily found. If nobody can find your website, then it isn't very useful. One thing you can do to help is by creating URLs that contain useful information. Google will usually rank a site higher with a URL like http://www.northwind.com/products/3/aniseed-syrup compared to http://www.northwind.com/products/3. In addition to being ranked higher by search engines, it is a lot easier for humans to remember as well. I am going to show you an easy way to create these SEO-style routes for your ASP.net MVC 3 applications.

The first thing we need to do in order to get this to work is create a route that will match this pattern:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.MapRoute(
        "ProductDetails",
        "products/{productId}/{productName}", // URL
        new { controller = "Products", action = "Details", productName = UrlParameter.Optional }, // URL Defaults
        new { id = @"\d+" } // URL Constraints
    );
}

What this does is register a route in our application that matches the pattern /products/id/ and optionally /products/id/name. The product name is optional but the id is required and must be an integer.

Now that we have our route in place we need to create the controller that will handle requests that match the route:

public class ProductsController : Controller
{
    public ActionResult Index(int id, string productName)
    {
        // retrieve the product from the database
        Product product = db.Products.Single(p => p.ProductID == id);

        return View(product);
    }
}

This controller action will take in an id and a product name, retrieve a product based on the id and then return the view, passing in the Product data. You might have noticed that the controller isn't using the productName at the moment. Currently, if we have a product that contains spaces, the URL will encode the string like so:

http://www.northwind.com/products/3/aniseed%20syrup

This is far from ideal. Let's go ahead and fix that problem.

public static class StringHelpers
{
    public static string ToSeoUrl(this string url)
    {
        // make the url lowercase
        string encodedUrl = (url ?? "").ToLower();

        // replace & with and
        encodedUrl = Regex.Replace(encodedUrl, @"\&+", "and");

        // remove characters
        encodedUrl = encodedUrl.Replace("'", "");

        // remove invalid characters
        encodedUrl = Regex.Replace(encodedUrl, @"[^a-z0-9]", "-");

        // remove duplicates
        encodedUrl = Regex.Replace(encodedUrl, @"-+", "-");

        // trim leading & trailing characters
        encodedUrl = encodedUrl.Trim('-');

        return encodedUrl;
    }
}

The above code creates an extension method for the string type and returns an "SEO-encoded" URL using the following steps:

  1. Convert the string to lowercase.
  2. Replace the & symbol with the word and
  3. Remove unwanted characters by replacing with a space (currently only ')
  4. Replace all other characters other than letters/numbers with a -
  5. Remove duplicate -'s from the string (we don't want aniseed--syrup, etc.)
  6. Remove leading/trailing -'s from the string

Now, a string like "AnIseeD Syrup" will be converted to "aniseed-syrup". Now we can modify our controller to make use of this functionality.

public class ProductsController : Controller
{
    public ActionResult Index(int id, string productName)
    {
        // retrieve the product from the database
        Product product = db.Products.Single(p => p.ProductID == id);

        // make sure the productName for the route matches the encoded product name
        string expectedName = product.ProductName.ToSeoUrl();
        string actualName = (productName ?? "").ToLower();

        // permanently redirect to the correct URL
        if( expectedName != actualName )
        {
            return RedirectToActionPermanent("Index", "Products", new { id = product.ProductID, productName = expectedName });
        }
        
        return View(product);
    }
}

This updated controller will do an HTTP 301 redirect if the product name in the URL does not match what it should be, or if it wasn't provided at all. A 301 redirect will tell a search engine to permanently re-index the content. If the user types http://www.northwind.com/products/3 or http://www.northwind.com/products/3/aniseed or any other URL other than http://www.northwind.com/products/3/aniseed-syrup then it will automatically redirect them to the correct one.

The final piece to wire this all up is to make sure your views are creating the proper links. We don't want the requests to redirect by default, otherwise every request will make two calls to the database. Here I am going to use the new MVC 3 View Engine Razor, but it could be done just as easily using the Web Forms View Engine.

@model IEnumerable<Models.Product>
@using Mvc.Helpers

<table>
   <tr>
      <th>Edit</th>
      <th>Product Name</th>
   </tr>
   
   @foreach( var product in Model )
   {
      <tr>
         <td>@Html.ActionLink("Edit", "Details", new { id = product.ProductID, productName = product.ProductName.ToSeoUrl() })</td>
         <td>@product.ProductName</td>
      </tr>
   }
</table>

That's all you need to do. Create an ActionLink and make sure you pass the productName value by calling our ToSeoUrl() helper. Hopefully you found this technique as helpful as I did.