Skip to content
Archive of entries posted by

Dealing with Direct Object References in ASP MVC

If you are not familiar with OWASP site, I highly encourage you take a look at it.  I think everyone can learn something by reading this site.  More specifically, I wanted to concentrate on one of the top 10 mistakes, Insecure Direct Object References.

If you take a look at most of ASP.NET MVC sample applications, you will notice that they are subject to this mistake.  So, if you create a sample application, then add Entity Framework code first context with a table that is using integer primary key, then create new controller with CRUD actions from the add new controller window, then run the app, you will immediately notice that your edit, details and delete links have that primary key as part of the URI.  For example, if you follow Edit link, you will see something like the following in your URI: http://localhost:12345/Products/Edit/1, where 1 is primary key.  If you are creating an intranet site that hosts homogenous data in Product table, you are probably OK.  However, imagine you write a multitenant  internet application, IDs 1 and 2 could belong to two different tenants of you application.  As a result, tenant 1 can see data from tenant 2 by simply incrementing a primary key in the URI.  Now, you have a serious problem on your hands. 

Some of the solutions you might use are

  • Replace integer primary keys with GUIDs
  • Somehow compute hash of the key, then decipher what it is in your controller

I am not a giant fan of first solution, and neither is 99.9 percent of DBAs out there.  You can add a candidate key that is a GUID and use it, but again you make your database less efficient.  What I am going to describe in this post is second solution. 

What I want to do is make sure that the solution will require minimum effort for me to implement and is robust enough.  I am going with encryption now, using a class I described here as a base.  What I am going to do is encrypt this integer primary key when I build the list of products as follows:

@using MvcValidation.Helpers
@model IEnumerable<MvcValidation.Data.Product>
@{
    ViewBag.Title = "Index";
}
<h2>
    Index</h2>
<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table>
    <tr>
        <th>
            Name
        </th>
        <th>
            Start Date
        </th>
        <th>
            End Date
        </th>
        <th>
            Minimum Quantity
        </th>
        <th>
            Maximum Quantity
        </th>
        <th>
        </th>
    </tr>
    @foreach (var item in Model)
    {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Name)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.BeginDate)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.EndDate)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.BeginQuantity)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.EndQuantity)
            </td>
            <td>
                @Html.ActionLink("Edit", "Edit", new { id =
                    EncryptionUtility.Encrypt(item.Id.ToString(), ViewData["Password"].ToString(), true) })
                @Html.ActionLink("Details", "Details", new { id =
                    EncryptionUtility.Encrypt(item.Id.ToString(), ViewData["Password"].ToString(), true) })
                @Html.ActionLink("Delete", "Delete", new { id =
                    EncryptionUtility.Encrypt(item.Id.ToString(), ViewData["Password"].ToString(), true) })
            </td>
        </tr>
    }
</table>

As you can see this code is very simple.  I did however had to modify my utility to make it URI friendly.  Because it is using Base 64 strings, it will potentially result in characters such as “/” or “+”, which will break URIs.  So, I update the utility to take another parameter to take care of this little problem.

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace MvcValidation.Helpers
{
    public static class EncryptionUtility
    {

        /// <summary>
        /// Encrypt the data
        /// </summary>
        /// <param name="input">String to encrypt</param>
        /// <param name="password">The password.</param>
        /// <param name="uriFriendly">if set to <c>true</c> produce URI friendly output.</param>
        /// <returns>
        /// Encrypted string
        /// </returns>
        public static string Encrypt(string input, string password, bool uriFriendly = false)
        {
            if (password.Length < 8)
            {
                password = (password + "zzzzzzzz").Substring(0, 8);
            }
            byte[] utfData = Encoding.UTF8.GetBytes(input);
            byte[] saltBytes = Encoding.UTF8.GetBytes(password);
            string encryptedString;
            using (var aes = new AesManaged())
            {
                var rfc = new Rfc2898DeriveBytes(password, saltBytes);

                aes.BlockSize = aes.LegalBlockSizes[0].MaxSize;
                aes.KeySize = aes.LegalKeySizes[0].MaxSize;
                aes.Key = rfc.GetBytes(aes.KeySize / 8);
                aes.IV = rfc.GetBytes(aes.BlockSize / 8);

                using (var encryptTransform = aes.CreateEncryptor())
                {
                    using (var encryptedStream = new MemoryStream())
                    {
                        using (var encryptor =
                            new CryptoStream(encryptedStream, encryptTransform, CryptoStreamMode.Write))
                        {
                            encryptor.Write(utfData, 0, utfData.Length);
                            encryptor.Flush();
                            encryptor.Close();

                            byte[] encryptBytes = encryptedStream.ToArray();
                            encryptedString = Convert.ToBase64String(encryptBytes);
                        }
                    }
                }
            }
            if (uriFriendly)
            {
                encryptedString = encryptedString.Replace("+", "-").Replace("/", "_");
            }
            return encryptedString;
        }

        /// <summary>
        /// Decrypt a string
        /// </summary>
        /// <param name="input">Input string in base 64 format</param>
        /// <param name="password">The password.</param>
        /// <param name="uriFriendly">if set to <c>true</c> produce URI friendly output.</param>
        /// <returns>
        /// Decrypted string
        /// </returns>
        public static string Decrypt(string input, string password, bool uriFriendly = false)
        {
            if (password.Length < 8)
            {
                password = (password + "zzzzzzzz").Substring(0, 8);
            }
            if (uriFriendly)
            {
                input = input.Replace("-", "+").Replace("_", "/");
            }
            byte[] encryptedBytes = Convert.FromBase64String(input);
            byte[] saltBytes = Encoding.UTF8.GetBytes(password);
            string decryptedString;
            using (var aes = new AesManaged())
            {
                var rfc = new Rfc2898DeriveBytes(password, saltBytes);
                aes.BlockSize = aes.LegalBlockSizes[0].MaxSize;
                aes.KeySize = aes.LegalKeySizes[0].MaxSize;
                aes.Key = rfc.GetBytes(aes.KeySize / 8);
                aes.IV = rfc.GetBytes(aes.BlockSize / 8);

                using (var decryptTransform = aes.CreateDecryptor())
                {
                    using (var decryptedStream = new MemoryStream())
                    {
                        var decryptor =
                            new CryptoStream(decryptedStream, decryptTransform, CryptoStreamMode.Write);
                        decryptor.Write(encryptedBytes, 0, encryptedBytes.Length);
                        decryptor.Flush();
                        decryptor.Close();

                        byte[] decryptBytes = decryptedStream.ToArray();
                        decryptedString =
                            Encoding.UTF8.GetString(decryptBytes, 0, decryptBytes.Length);
                    }
                }
            }

            return decryptedString;
        }
    }
}

This code for URI friendliness is pretty simple.  I also altered the code to make sure it will automatically handle password (salt) that is smaller than 8 characters.  You will kno0w shortly as to why I did that.  Because the utility produces same results with the same input and password, I will end up with the following issue.  If I have products and categories controllers, both will produce the same URI for the same integer ID.  I want to make it a bit more secure, so I am going to use controller name as the key.  So, the password will be set by controller as follows:

using System.Data;
using System.Linq;
using System.Web.Mvc;
using MvcValidation.Data;

namespace MvcValidation.Controllers
{
    public class ProductController : Controller
    {
        private readonly ProductContext _db = new ProductContext();

        //
        // GET: /Product/

        public ViewResult Index()
        {
            ViewData.Add("Password", GetType().Name.Replace("Controller", "").ToLower());
            return View(_db.Products.ToList());
        }

I could probably use full class name as well, but I want to avoid writing decryption code in controllers, thus I want to use MVC routing to decrypt the data.  I am going to write a custom route that does exactly that.

using System.Web;
using System.Web.Routing;
using MvcValidation.Helpers;

namespace MvcValidation.Routing
{
    public class RouteWithEncryption : RouteBase
    {
        private readonly RouteBase _inner;

        /// <summary>
        /// Initializes a new instance of the <see cref="RouteWithEncryption"/> class.
        /// </summary>
        /// <param name="routeToWrap">The route to wrap.</param>
        public RouteWithEncryption(RouteBase routeToWrap)
        {
            _inner = routeToWrap;
        }

        /// <summary>
        /// When overridden in a derived class, returns route information about the request.
        /// </summary>
        /// <param name="httpContext">An object that encapsulates information about the HTTP request.</param>
        /// <returns>
        /// An object that contains the values from the route definition if the route matches the current request, or null if the route does not match the request.
        /// </returns>
        public override RouteData GetRouteData(HttpContextBase httpContext)
        {
            var routeData = _inner.GetRouteData(httpContext);
            if (routeData != null)
            {
                if (routeData.Values.ContainsKey("id") && routeData.Values.ContainsKey("controller") && routeData.Values.ContainsKey("action"))
                {
                    var id = routeData.Values["id"].ToString();
                    if (!string.IsNullOrEmpty(id))
                    {
                        var password = routeData.Values["controller"].ToString().ToLower();
                        int test;
                        if (!int.TryParse(id, out test))
                        {
                            var replacement = EncryptionUtility.Decrypt(id, password, true);
                            routeData.Values["id"] = replacement;
                        }
                    }
                }
            }
            return routeData;
        }

        /// <summary>
        /// When overridden in a derived class, checks whether the route matches the specified values, and if so, generates a URL and retrieves information about the route.
        /// </summary>
        /// <param name="requestContext">An object that encapsulates information about the requested route.</param>
        /// <param name="values">An object that contains the parameters for a route.</param>
        /// <returns>
        /// An object that contains the generated URL and information about the route, or null if the route does not match <paramref name="values"/>.
        /// </returns>
        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
        {
            return _inner.GetVirtualPath(requestContext, values);
        }
    }
}

As you can see, I am pulling controller name and ID from route values collection and decrypting the ID using controller name as password.  Voila, now you know why I use controller name.  Now, I am going to update all routes to use my encrypting route in Global.asax.cs:

using System.Web.Mvc;
using System.Web.Routing;
using MvcValidation.Routing;

namespace MvcValidation
{
    // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
    // visit http://go.microsoft.com/?LinkId=9394801

    public class MvcApplication : System.Web.HttpApplication
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
        }

        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
                "Default", // Route name
                "{controller}/{action}/{id}", // URL with parameters
                new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
            );

            for (var i = 0; i < routes.Count; i++)
            {
                routes[i] = new RouteWithEncryption(routes[i]);
            }
        }

That is it, now we have hidden primary keys from users.  You can download entire solution here.

Thanks.

Post to Twitter

Validation Inside jQuery Accordion

I recently uncovered a little issue with using entry controls that use unobtrusive JavaScript validation inside jQuery accordion control.  When an error is shown, the accordion does not resize as it should, thus some controls fall off the accordion surface.  I got some feedback on  ASP.NET forum from Bruce, and wrote a little function that does accordion resizing.  You just need to call the function after the form has been loaded and jQuery initialized.  I wanted to post the code here on my blog as well as forum, mostly for my own benefit.  Yes, I am selfish :-)

 hookupErrorPlacementAndResize: function () {
    var currentForm = $('form');
    $.each(currentForm, function () {
        var validator = $(this).data('validator');
        var errorPlacement = validator.settings.errorPlacement;
        validator.settings.errorPlacement = function (error, element) {
             if (errorPlacement) {
                   errorPlacement(error, element);
            }
       $('.accordion_class').accordion('resize');
     };
   });
 }

If you have multiple forms, you can always change the code to take form name as a parameter to the function.  All function does is override errorPlacement function used by jQuery validation and hooks up additional code to resize accordions based on class.  You can always change that as well and use names.

Thanks.

Post to Twitter

Windows 8 Metro Applications and the Azure (Cont.)

As I mentioned before, I am going to write the last post about integrating Windows 8 Metro applications with Azure.

First of, let’s take a look at securing our service with Forms Authentication.  I blogged about that as well, and the only change is that I am going to use REST for authentication service.  Here is the interface for my service – it is very simple:

    [ServiceContract]
    public interface ILoginService
    {
        [OperationContract]
        [WebGet(UriTemplate = "/Login/?userName={userName}&password={password}",
            RequestFormat = WebMessageFormat.Json,
            ResponseFormat = WebMessageFormat.Json)]
        bool Login(string userName, string password);

The implementation is using Users table I mentioned before:

    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
    public class LoginService : ILoginService
    {
        public bool Login(string userName, string password)
        {
            bool returnValue = false;
            using (var context = new QuotesContext())
            {
                var user = context.Users.FirstOrDefault(one => one.UserName == userName);

                if (user != null)
                {
                    returnValue = (user.Password == password);
                }
            }
            if (returnValue)
            {
                var ticket =
                    new FormsAuthenticationTicket(
                        1,
                        userName,
                        DateTime.Now,
                        DateTime.Now.AddHours(24),
                        false,
                        "",
                        FormsAuthentication.FormsCookiePath);

                string encryptedTicket = FormsAuthentication.Encrypt(ticket);
                var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket)
                {
                    Path = FormsAuthentication.FormsCookiePath,
                    Expires = DateTime.Now.AddHours(24)
                };

                HttpContext.Current.Response.Cookies.Add(cookie);
            }
            return returnValue;
        }

The code is pretty straight forward as you can see.  Just match user name and password and create authentication cookie to be passed back to the client.

Now on Windows 8 side the code is just as easy, I am just going to use HttpClient class:

var client = new System.Net.Http.HttpClient();

            var responce = await client.GetAsync(new Uri("http://xxxx.cloudapp.net/LoginService.svc/Login/?userName=admin@system.com&password=_Random1"));
            var text = await responce.Content.ReadAsStringAsync();
            if (text.ToLower().Equals("true"))
            {
                responce = await client.GetAsync(new Uri("http://xxxxx.cloudapp.net/QuoteService.svc/GetQuote"));
                text = await responce.Content.ReadAsStringAsync();
                if (text.LastIndexOf("-") >= 0)
                {
                    text = text.Substring(0, text.Replace("--", "-").LastIndexOf("-")) + Environment.NewLine + text.Substring(text.Replace("--", "-").LastIndexOf("-"));
                }
                text = text.Replace("  ", " ");
                if (text.StartsWith("\""))
                {
                    text = text.Substring(1);
                }
                if (text.EndsWith("\""))
                {
                    text = text.Substring(0, text.Length - 1);
                }
                QuoteBlock.Text = text.Trim();
                quoteGrid.Visibility = Windows.UI.Xaml.Visibility.Visible;
            }

Getting the data from protected service is a two step process.  I am first calling authentication service, passing user and password as query string parameters, then I verify that authentication was successful, then I call the real service using the same instance of the HttpClient, which will pass my authentication cookie.  The rest of the code just deal with return value processing.

As far as updating the tile, the story is less bright in my opinion.  According to Microsoft there is not way to secure the end point that tile updater will call.  So, I cannot do what I wanted to.  Not only that, but processing XML that file updater expects does not work properly when you create it from XDcoument.  So, here is the solution I came up with.  I am going to simply create a text file with a placeholder for the actual content, then write worker role that would get the content, then update the XML, then upload it to Azure Blob Storage.  Then I can retrieve very simply by calling

PeriodicUpdateRecurrence recurrence = PeriodicUpdateRecurrence.HalfHour;

System.Uri url = new Uri("http://xxxx.blob.core.windows.net/quotes/quote?sr=b&si=Random&sig=VUErCXWGIczO9pLLNI4nc4m2DTTixUg%2F9%2F2qYqY1BAY%3D");

TileUpdateManager.CreateTileUpdaterForApplication().StartPeriodicUpdate(url, recurrence);

You can use for example  https://www.myazurestorage.com/ to create a blob container and set access policy on it as well as create a URL to a specific blob entry.  That is what I did, and you can see my policy called Random as part of the URL above.  There is also no easy way to troubleshoot the process if you get any steps wrong.  Here is an example tile XML you can just upload to blob storage for testing.  I know it works.

<tile>
  <visual lang=”en-US”>
    <binding template=”TileWideText03″>
      <text id=”1″>Testing 123…</text>
    </binding> 
  </visual>
</tile>

Enjoy.

Post to Twitter

Validating Dependent Fields in ASP.NET MVC

In this post I wanted to describe a solution to a specific problem I recently encountered.  The problem is as following.  I have a class with a set of dependent properties, such as start and end date or minimum / maximum numbers.  I want to implement both client and server side validation in an MVC application using attributes.  I really like how attributes work in MVC application that is why I picked that specific solution.  Since I want good interactive user experience, I want to make sure the same validation works in JavaScript.  I am going to build my validation by plugging into jQuery validation framework.

I am now going to assume the following:

  • You created new MVC 3 project using Razor
  • I added Entity Framework to the project
  • I updated all packages to the latest version

Cool, now that we established ground work, le’s describe the solution.  Let’s start with a Product class.

using System;
using System.ComponentModel.DataAnnotations;

namespace MvcValidation.Data
{
    public class Product
    {
        public int Id { get; set; }

        [StringLength(30)]
        [Required]
        public string Name { get; set; }

        [Display(Name = "Start Date")]
        [DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
        [CompareDates("EndDate", ErrorMessage = "Start date cannot be before end date")]
        public DateTime? BeginDate { get; set; }

        [Display(Name = "End Date")]
        [DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
        [CompareDates("BeginDate", ErrorMessage = "Start date cannot be before end date")]
        public DateTime? EndDate { get; set; }

        [Display(Name = "Min. Quantity")]
        [CompareNumbers("EndQuantity", ErrorMessage = "Min cannot be more than max")]
        public int BeginQuantity { get; set; }

        [Display(Name = "Max. Quantity")]
        [CompareNumbers("BeginQuantity", ErrorMessage = "Min cannot be more than max")]
        public int EndQuantity { get; set; }
    }
}

As you can see from above, I am going to create a couple of attributes, one to compare number, the other to compare dates.  I am going to cover one in details, and the other one is very similar of course.  To create a validation attribute, such as CompareNumbers, I am going to extend a base class, ValidationAttribute.  Then, I am going to implement an IClientValidatable interface.  This intercface only needs one method, the one that returns validation rules collection. In my case, I only need one rule.

First, server side.  I am going to override IsValid method.and implement simple logic.  To do that, I need to have access to two things, current value which is passed into this method, and the other property value that I need to compare this value to.  To simplify the setup my logic assumes that if property name contains word “begin”, it would be a start (smaller value).  Otherwise, I am going to assume that I am looking at the larger value of the two.

/// <summary>
        /// Validates the specified value with respect to the current validation attribute.
        /// </summary>
        /// <param name="value">The value to validate.</param>
        /// <param name="validationContext">The context information about the validation operation.</param>
        /// <returns>
        /// An instance of the <see cref="T:System.ComponentModel.DataAnnotations.ValidationResult"/> class.
        /// </returns>
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            var result = ValidationResult.Success;
            var otherValue = validationContext.ObjectType.GetProperty(OtherPropertyName).GetValue(validationContext.ObjectInstance, null);
            if (value != null)
            {
                decimal currentDecimalValue;
                if (decimal.TryParse(value.ToString(), out currentDecimalValue))
                {

                    if (otherValue != null)
                    {
                        decimal otherDecimalValue;
                        if (decimal.TryParse(otherValue.ToString(), out otherDecimalValue))
                        {
                            if (!OtherPropertyName.ToLower().Contains("begin"))
                            {
                                if (currentDecimalValue > otherDecimalValue)
                                {
                                    result = new ValidationResult(ErrorMessage);
                                }
                            }
                            else
                            {
                                if (currentDecimalValue < otherDecimalValue)
                                {
                                    result = new ValidationResult(ErrorMessage);
                                }
                            }
                            if (currentDecimalValue == otherDecimalValue && !AllowEquality)
                            {
                                result = new ValidationResult(ErrorMessage);
                            }
                        }
                    }
                }
            }
            return result;
        }

If you look at the logic, you can see that I am doing null check first, then converting current value to decimal.  if you want to extend this validation to double type, you can easily do that.  Also, I have a check for equal values, and in this case I am going to use explicit property value of the attribute.  let me show you the entire class now:

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;

namespace MvcValidation.Data
{
    /// <summary>
    /// Compares two dates to each other, ensuring that one is larger than the other
    /// </summary>
    [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
    public class CompareNumbersAttribute : ValidationAttribute, IClientValidatable
    {

        /// <summary>
        /// Initializes a new instance of the <see cref="CompareNumbersAttribute"/> class.
        /// </summary>
        /// <param name="otherPropertyName">Name of the compare to date property.</param>
        /// <param name="allowEquality">if set to <c>true</c> equal dates are allowed.</param>
        public CompareNumbersAttribute(string otherPropertyName, bool allowEquality = true)
        {
            AllowEquality = allowEquality;
            OtherPropertyName = otherPropertyName;
        }

        #region Properties

        /// <summary>
        /// Gets the name of the  property to compare to
        /// </summary>
        public string OtherPropertyName { get; private set; }

        /// <summary>
        /// Gets a value indicating whether dates could be the same
        /// </summary>
        public bool AllowEquality { get; private set; }

        #endregion

        /// <summary>
        /// Validates the specified value with respect to the current validation attribute.
        /// </summary>
        /// <param name="value">The value to validate.</param>
        /// <param name="validationContext">The context information about the validation operation.</param>
        /// <returns>
        /// An instance of the <see cref="T:System.ComponentModel.DataAnnotations.ValidationResult"/> class.
        /// </returns>
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            var result = ValidationResult.Success;
            var otherValue = validationContext.ObjectType.GetProperty(OtherPropertyName).GetValue(validationContext.ObjectInstance, null);
            if (value != null)
            {
                decimal currentDecimalValue;
                if (decimal.TryParse(value.ToString(), out currentDecimalValue))
                {

                    if (otherValue != null)
                    {
                        decimal otherDecimalValue;
                        if (decimal.TryParse(otherValue.ToString(), out otherDecimalValue))
                        {
                            if (!OtherPropertyName.ToLower().Contains("begin"))
                            {
                                if (currentDecimalValue > otherDecimalValue)
                                {
                                    result = new ValidationResult(ErrorMessage);
                                }
                            }
                            else
                            {
                                if (currentDecimalValue < otherDecimalValue)
                                {
                                    result = new ValidationResult(ErrorMessage);
                                }
                            }
                            if (currentDecimalValue == otherDecimalValue && !AllowEquality)
                            {
                                result = new ValidationResult(ErrorMessage);
                            }
                        }
                    }
                }
            }
            return result;
        }

        /// <summary>
        /// When implemented in a class, returns client validation rules for that class.
        /// </summary>
        /// <param name="metadata">The model metadata.</param>
        /// <param name="context">The controller context.</param>
        /// <returns>
        /// The client validation rules for this validator.
        /// </returns>
        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            var rule = new ModelClientValidationRule
            {
                ErrorMessage = ErrorMessage,
                ValidationType = "comparenumbers"
            };
            rule.ValidationParameters["otherpropertyname"] = OtherPropertyName;
            rule.ValidationParameters["allowequality"] = AllowEquality ? "true" : "";
            yield return rule;
        }
    }
}

As you can see, I have two properties that I am setting from the constructor – the other property name and a flag that allows values to be equal, which is my default.  If you take a look at the last method, you can see that I am injecting those two properties’ values into the HTML of the page via jQuery validation and unobtrusive validation frameworks.  Unobtrusive validation works off data-val-* attributes that MVC automatically injects for me into my HTML and jQuery parses those, establishing client side validation rules.

Here is how I am going to approach client side.  I am going to write a JavaScript function, similar to IsValid method you saw above.  To inject this method into jQuery validation, I just need to call two methods in jQuery: I need to add an adapter via adapters.add method that would adept data-val-* attribute values and will map them to parameters passed into my function, which in turn is added via addMethod call.  Once that is done, I am going to subscribe to blur (lost focus) method of the “other” control and run its validation at that point.  So, if I got it all right, as soon I change a value of Begin*** text box, then tab out, both that textbox and End*** textbox’s value will be validated by my custom method.

So, here is how I am going to add an adapter:

    $.validator.unobtrusive.adapters.add('comparenumbers', ['otherpropertyname', 'allowequality'],
        function (options) {
            options.rules['comparenumbers'] = options.params;
            if (options.message) {
                options.messages['comparenumbers'] = options.message;
            }
        }
    );

As you can see, I just need to le jQuery know about my property names of the original validation attribute.  All values and names must be in lower case though, or you will get errors from jQuery.  These values also include error message that I originally set on the attribute constructor called from my Product class (see class definition above.).

Next step is to add my validation function:

$.validator.addMethod('comparenumbers', function (value, element, params) {
    var otherFieldValue = $('input[name="' + params.otherpropertyname + '"]').val();
    if (otherFieldValue && value) {
        var currentValue = parseFloat(value);
        var otherValue = parseFloat(otherFieldValue);
        if ($(element).attr('name').toLowerCase().indexOf('begin') >= 0) {
            if (params.allowequality) {
                if (currentValue > otherValue) {
                    return false;
                }
            } else {
                if (currentValue >= otherValue) {
                    return false;
                }
            }
        } else {
            if (params.allowequality) {
                if (currentValue < otherValue) {
                    return false;
                };
            } else {
                if (currentValue <= otherValue) {
                    return false;
                };
            }
        }
    }
    customValidation.addDependatControlValidaitonHandler(element, params.otherpropertyname);
    return true;
}, '');

Code is pretty simple as you can see.  Again, I am relying on property names (control names to be precise), but those do match because this is how MVC engine creates controls corresponding to properties.  I am also doing null checks and calling parseFloat methods.  I also check equality property value.   I rely on the fact that in JavaScript non empty string check returns True in my if statement.  The last line of code is interesting.  I have a helper class that is responsible for wiring up dependent controls via addDependatControlValidaitonHandler method.  let’s take a look at this helper class.

window.customValidation = window.customValidation ||
    {
        relatedControlValidationCalled: function (event) {
            if (!customValidation.activeValidator) {
                customValidation.formValidator = $(event.data.source).closest('form').data('validator');
            }
            customValidation.formValidator.element($(event.data.target));
        },
        relatedControlCollection: [],
        formValidator: undefined,
        addDependatControlValidaitonHandler: function (element, dependentPropertyName) {
            var id = $(element).attr('id');
            if ($.inArray(id, customValidation.relatedControlCollection) < 0) {
                customValidation.relatedControlCollection.push(id);
                $(element).on(
                    'blur',
                    { source: $(element), target: $('#' + dependentPropertyName) },
                    customValidation.relatedControlValidationCalled);
            }
        }
    };

My method addDependatControlValidaitonHandler checks to see if customValidation already tracks the dependent control, and if not, adds it to wired controls collection (relatedControlsCollection property).  First time validation is called, I am also grabbing validator object from the form to use with calls.  This is an optimization trick.  In the addDependatControlValidaitonHandler I also attach an event handler to the ‘blur’ (lost focus) event of the related control. I am using a few utility method from jQuery to accomplish that, such as on and inArray.

As far as dates validation goes, the only difference is parsing.

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;

namespace MvcValidation.Data
{
    /// <summary>
    /// Compares two dates to each other, ensuring that one is larger than the other
    /// </summary>
    [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
    public class CompareDatesAttribute : ValidationAttribute, IClientValidatable
    {

        /// <summary>
        /// Initializes a new instance of the <see cref="CompareDatesAttribute"/> class.
        /// </summary>
        /// <param name="otherPropertyName">Name of the compare to date property.</param>
        /// <param name="allowEquality">if set to <c>true</c> equal dates are allowed.</param>
        public CompareDatesAttribute(string otherPropertyName, bool allowEquality = true)
        {
            AllowEquality = allowEquality;
            OtherPropertyName = otherPropertyName;
        }

        #region Properties

        /// <summary>
        /// Gets the name of the  property to compare to
        /// </summary>
        public string OtherPropertyName { get; private set; }

        /// <summary>
        /// Gets a value indicating whether dates could be the same
        /// </summary>
        public bool AllowEquality { get; private set; }

        #endregion

        /// <summary>
        /// Validates the specified value with respect to the current validation attribute.
        /// </summary>
        /// <param name="value">The value to validate.</param>
        /// <param name="validationContext">The context information about the validation operation.</param>
        /// <returns>
        /// An instance of the <see cref="T:System.ComponentModel.DataAnnotations.ValidationResult"/> class.
        /// </returns>
        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            var result = ValidationResult.Success;
            var otherValue = validationContext.ObjectType.GetProperty(OtherPropertyName)
                .GetValue(validationContext.ObjectInstance, null);
            if (value != null)
            {
                if (value is DateTime)
                {

                    if (otherValue != null)
                    {
                        if (otherValue is DateTime)
                        {
                            if (!OtherPropertyName.ToLower().Contains("begin"))
                            {
                                if ((DateTime)value > (DateTime)otherValue)
                                {
                                    result = new ValidationResult(ErrorMessage);
                                }
                            }
                            else
                            {
                                if ((DateTime)value < (DateTime)otherValue)
                                {
                                    result = new ValidationResult(ErrorMessage);
                                }
                            }
                            if ((DateTime)value == (DateTime)otherValue && !AllowEquality)
                            {
                                result = new ValidationResult(ErrorMessage);
                            }
                        }
                    }
                }
            }
            return result;
        }

        /// <summary>
        /// When implemented in a class, returns client validation rules for that class.
        /// </summary>
        /// <param name="metadata">The model metadata.</param>
        /// <param name="context">The controller context.</param>
        /// <returns>
        /// The client validation rules for this validator.
        /// </returns>
        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            var rule = new ModelClientValidationRule
            {
                ErrorMessage = ErrorMessage,
                ValidationType = "comparedates"
            };
            rule.ValidationParameters["otherpropertyname"] = OtherPropertyName;
            rule.ValidationParameters["allowequality"] = AllowEquality ? "true" : "";
            yield return rule;
        }
    }
}
$.validator.unobtrusive.adapters.add('comparedates', ['otherpropertyname', 'allowequality'],
        function (options) {
            options.rules['comparedates'] = options.params;
            if (options.message) {
                options.messages['comparedates'] = options.message;
            }
        }
    );

$.validator.addMethod('comparedates', function (value, element, params) {
    var otherFieldValue = $('input[name="' + params.otherpropertyname + '"]').val();
    if (otherFieldValue && value) {
        var currentValue = Date.parse(value);
        var otherValue = Date.parse(otherFieldValue);
        if ($(element).attr('name').toLowerCase().indexOf('begin') >= 0) {
            if (params.allowequality) {
                if (currentValue > otherValue) {
                    return false;
                }
            } else {
                if (currentValue >= otherValue) {
                    return false;
                }
            }
        } else {
            if (params.allowequality) {
                if (currentValue < otherValue) {
                    return false;
                }
            } else {
                if (currentValue <= otherValue) {
                    return false;
                }
            }
        }
    }
    customValidation.addDependatControlValidaitonHandler(element, params.otherpropertyname);
    return true;
}, '');

That is all there is to it.  My cshtml page looks the same as the one without this validation, which is cool.  I like clean and simple HTML.

@model MvcValidation.Data.Product

@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Product</legend>

        <div class="editor-label">
            @Html.LabelFor(model => model.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Name)
            @Html.ValidationMessageFor(model => model.Name)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.BeginDate)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.BeginDate)
            @Html.ValidationMessageFor(model => model.BeginDate)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.EndDate)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.EndDate)
            @Html.ValidationMessageFor(model => model.EndDate)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.BeginQuantity)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.BeginQuantity)
            @Html.ValidationMessageFor(model => model.BeginQuantity)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.EndQuantity)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.EndQuantity)
            @Html.ValidationMessageFor(model => model.EndQuantity)
        </div>

        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>
<script type="text/javascript">
    $(function () {
        $('#BeginDate').datepicker();
        $('#EndDate').datepicker();
    });
</script>

One nice thing I also do is to use jQuery UI framework to turn my text boxes into date pickers.  To accomplish all that I am adding all my scripts and style sheets to _Layout.cshtml to avoid including them in every page.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>@ViewBag.Title</title>
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
    <link href="@Url.Content("~/Content/themes/base/jquery.ui.all.css")" rel="stylesheet" type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery-1.7.2.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/modernizr-2.5.3.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery-ui-1.8.19.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/customValidation.js")" type="text/javascript"></script>
</head>
<body>
    <div class="page">

You can download entire solution here.

Enjoy.

Post to Twitter

Windows 8 Metro Applications and the Azure

I wanted to start a short series of posts, describing my experience in building simple Windows 8 Metro application using XAML, C#, and a service in Azure. 

You can find my second post at http://dotnetspeak.com/index.php/2012/05/windows-8-metro-applications-and-the-azure-cont/

The application is very simple, it is a going to be a famous quote app, where the user can get an on demand random famous quote.  I am going to use a web service to generate an application.  On top of that, I am going to add a live tile to my Metro app that will periodically refresh with a new quote.  I will at the end publish all source code as well.

Here is the technology stack I am going to use

  • Window 8 Metro app
  • WCF (REST)
  • Entity Framework Code First
  • SQL Azure
  • Windows Azure

One note is that you can easily substitute Azure for your own hosting provider.  You can check out my previous blogs on that subject.

With the main premise out of the way, let’s get started.

I am going to login to my Azure portal, sign in and create new database.  I would like to support authentication, not wanting to make my service visible to whole internet unprotected, so I am going to add two tables: users and quotes.

I used Azure table designer to create tables, and it is very simple to use:

image

 

image

My data was in a resource (resx) file.  I wrote a quite little utility to pump the data into Azure SQL Server database:

 

using System;
using System.Data;
using System.Data.SqlClient;
using System.Resources;

namespace QuoteParser
{
    class Program
    {
        static void Main(string[] args)
        {

            var connString =
                "Server=tcp:myServer.database.windows.net,1433;Database=Quotes;User ID=myUser;Password=myPasword;Trusted_Connection=False;Encrypt=True;";

            using (var conn = new SqlConnection(connString))
            {
                conn.Open();

                ResourceManager manager = new ResourceManager(typeof(QuoteResource));
                for (int quoteNumber = 1; quoteNumber <= 1142; quoteNumber++)
                {
                    var property = typeof(QuoteResource).GetProperty("Q" + quoteNumber.ToString(),
                        System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);

                    string text = property.GetValue(null, null).ToString();
                    text = text.Replace(Environment.NewLine, "").Replace("'", "''");

                    using (var command = conn.CreateCommand())
                    {
                        command.CommandText =
                            string.Format("Insert into quotes ([QuoteText], [IsDeleted]) values ('{0}', 0)", text);
                        command.CommandType = CommandType.Text;
                        command.ExecuteNonQuery();
                    }
                }
            }
        }
    }
}

I know this could be cleaned up, but I am not concerned about that right this minute.

Now, the service.  I am going to use VS 2010 for this since I have Azure SDK already installed on my machine.  I create brand new project

image

Then I use QCF service template.

image

Now click OK to create base project along with standard WCF project.  The WCF template is pretty standard.  I am going to clean it up and create two methods I am going to need – one to generate a quote, one to create a tile output.

Now, I am going to create my EF classes.  Since I have local copy of the same database, I am going to use Power Tools to reverse engineer my EF classes.

I am not going to concentrate on that task, it is pretty basic and just reflects table structure you saw above.

Now, the service.  I am going to write two methods – one to get a quote, the other to get a tile:

using System.ServiceModel;
using System.ServiceModel.Web;

namespace QuotesWCFServiceWebRole
{

    [ServiceContract]
    public interface IQuoteService
    {

        [OperationContract]
        [WebGet(UriTemplate = "/GetQuote",
            ResponseFormat = WebMessageFormat.Json,
            RequestFormat = WebMessageFormat.Json)]
        string GetQuote();

        [OperationContract]
        [WebGet(UriTemplate = "/GetQuoteTile",
            ResponseFormat = WebMessageFormat.Json,
            RequestFormat = WebMessageFormat.Json)]
        string GetQuoteTile();
    }

}

 

Please easy so far.  The implementation is just as trivial.

using System;
using System.IO;
using System.Linq;
using QuotesWCFServiceWebRole.Models;
using System.Xml.Linq;

namespace QuotesWCFServiceWebRole
{

    public class QuoteService : IQuoteService
    {

        public string GetQuote()
        {
            Quote quote = null;
            using (var context = new QuotesContext())
            {
                var max = context.Quotes.Max(one => one.QuoteID);

                while (quote == null)
                {
                    var random = (new Random(DateTime.Now.Millisecond)).Next(1, max);
                    quote = context.Quotes.FirstOrDefault(one => one.QuoteID == random);
                }
            }
            return quote.QuoteText;
        }
        /// <summary>
        /// Sample tile return value        
        /// standard XML header with utf-8 encoding 
        /// <tile>
        ///     <visual lang="en-US">
        ///         <binding template="TileWideText03">
        ///             <text id="1">Text Header Field 1</text>
        ///         </binding>  
        ///     </visual>
        ///</tile>
        /// </summary>
        /// <returns></returns>
        public string GetQuoteTile()
        {
            var quoteText = GetQuote();

            if (quoteText.LastIndexOf("-", System.StringComparison.Ordinal) > 0)
            {
                var start = quoteText.Substring(0, quoteText.LastIndexOf("-", System.StringComparison.Ordinal));
                var end = quoteText.Substring(quoteText.LastIndexOf("-", System.StringComparison.Ordinal));
                quoteText = start + Environment.NewLine + end;
            }

            var textElement = new XElement("text", quoteText);
            textElement.SetAttributeValue("id", "1");

            var bindingElement = new XElement("binding", textElement);
            bindingElement.SetAttributeValue("template", "TileWideText03");

            var visualElement = new XElement("visual", bindingElement);
            visualElement.SetAttributeValue("lang", "en-US");

            var tileElement = new XElement("tile", visualElement);

            var doc = new XDocument(new XDeclaration("1.0", "utf-8", "yes"), tileElement);
            var writer = new StringWriter();
            doc.Save(writer);
            var returnValue =  writer.GetStringBuilder().ToString();
            return returnValue;
        }
    }
}

I decided not to hard code XML, but instead use XDocument class to ensure my XML is properly formatted and is valid.  At this point I can right-click on the WCF project (not Azure), then select Debug->Start  New Instance.  Now in your browser select svc file, then add my method name GetQuote.  Once that is done, I can easily test the service.  Do not worry, I want to test everything and do test deployment before adding authentication.  So, now I verified that my code is correct and I can get a quote or tile that is using property tile format based on specification found here.  Once important this I also want to show is web.config that I have to setup to make sure I expose correct binding – webBinding  Here is serviceModel portion of my web.config file

    <system.serviceModel>
        <protocolMapping>
            <add scheme="http" binding="webHttpBinding" />
        </protocolMapping>
        <bindings>
            <webHttpBinding>
                <binding name="webBinding">
                    <security mode="None" />
                </binding>
            </webHttpBinding>
        </bindings>
        <behaviors>
            <endpointBehaviors>
                <behavior name="webGetbehavior">
                    <webHttp helpEnabled="true" />
                </behavior>
                <behavior name="loginBehavior" />
            </endpointBehaviors>
            <serviceBehaviors>
                <behavior name="errorsInlcuded">
                    <serviceDebug includeExceptionDetailInFaults="true" />
                    <serviceMetadata httpGetEnabled="true" />
                    <serviceAuthorization principalPermissionMode="None" />
                </behavior>
                <behavior name="">
                    <serviceMetadata httpGetEnabled="true" />
                    <serviceDebug includeExceptionDetailInFaults="false" />
                </behavior>
            </serviceBehaviors>
        </behaviors>
        <services>
            <service name="QuotesWCFServiceWebRole.QuoteService" behaviorConfiguration="errorsInlcuded">
                <endpoint address="" contract="QuotesWCFServiceWebRole.IQuoteService" binding="webHttpBinding" bindingConfiguration="webBinding" behaviorConfiguration="webGetbehavior" />
            </service>
        </services>
        <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
    </system.serviceModel>

Now I need to publish to Azure.  I found a long time ago that the easiest way is to do that through Visual Studio Publish wizard instead of manually uploading package.  Just right click on Azure project, select publish and follow instructions.  You will have to sign in to your Azure account and download publish profile in the process, then import that profile in the wizard.  You may have to repeat the process if you get certificate error as initial run has to setup the certificate and storage account used for deployments.

Once that completes, use browser again, but use your Azure service address (URL).  Should be something like

http://mySpecialHostedServiceName.cloudapp.net/QuoteService.svc/GetQuoteTile

Everything worked great.  In the next post I will demonstrate how to secure the service and test that part through a small test hardness.

Enjoy.

Post to Twitter

Atlanta Code Camp 2012 Call For Speakers

As the Code Camp is nearing its scheduled date of May 19th, we are still looking for more speakers.  Our goal is to provide a wide variety of talks to serve many diverse interests of developers of Atlanta area.

If you would like to speak, it is not too late!

Submit your talks here.

I hope to see you there.

Post to Twitter

SSDT IntelliSense Not Working

I love new SSDT (SQL Server Data Tools) product from Microsoft.  I blogged about it a few times already.  One thing that was bugging me though is the face that IntelliSense was not working for me at all.  I have been ignoring that for a while being that I am busy and the fact that I could compose my stored procedures in SQL Server Management Studio if I had to.

I finally took a minute to figure out why, and the answer was dead simple.  For some reason the feature was disabled in options.  To enable it go to Tool -> Options menu in Visual Studio, expand Text Editor, then find  SQL Server tools, then check option on General and IntelliSense nodes.

 image

 

image

Hopefully I just saved someone a few minute of headache.

Enjoy.

Post to Twitter

Connection Pooling and Integration Tests

On my current project we recently started getting the following error while running integration tests as part of continuous integration build.

System.InvalidOperationException: Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.

I tested our application, and we did not have connection leaking problems, our connection were being disposed of after use.  So the issue was not in our code, but in unit tests.

We are using MSTest and TFS Build for our continuous integration implementation.  The errors started after we wrote sufficient number, well over a hundred of integration tests.  As I was trying to find out the reason, I came across some article that were stating that even though MS Test runs tests sequentially, but the initialization is run in parallel, one thread per test / test class.  In our initialization code we perform application login, which hits the database.  Since our configuration file does not specify connection pooling settings, we are use defaults you can see here.  So, default number of connections per pool is 100, which makes sense that the error showed up after we had over 100 tests.  The solution to the problem was very simple.  I simply added “Pooling=false” to the connection string that is used in unit test runs only. 

Hopefully this will save a few more folks a few minutes.

Thanks.

Post to Twitter

Atlanta Code Camp 2012

Exciting news for developers in Atlanta!  Atlanta annual Code Camp is almost here.  It is scheduled to commence on Saturday, May 19th at Southern Polytechnic State University in Marietta, GA.

This event is free to everyone that wishes to attend, as long as capacity is not exceeded in the event facilities.  We will offer coffee and lunch free of charge.

If you’re not familiar with code camps, they are free community‐focused events by and for the .NET developer community. The Atlanta Code Camp draws upon the expertise of local and regional developers, architects, and experts who come together to share their real world experiences, lessons learned, best practices, and general knowledge with other interested individuals.

This event is unique in that it is “for the community, by the community” and is free for all that desire to attend. In past years, the Atlanta Code Camp has provided free training and networking opportunities for 300 of the best, most motivated development professionals. With our larger facility, we’re expecting this year to be even bigger and better.

Learning and free food – what could be better?!!

Please visit home page for more details – http://www.atlantacodecamp.org/default.aspx

If you are a speaker, please submit your talks here.

You can register by clicking here

I hope to see every one there.

If you have any questions at all, please email us at CodeCamp [@] Live.com

If your company would like to be a sponsor of the event, please email us as well.  We have many sponsorship level available to suit your company needs.  Please email us for details.

Post to Twitter

Update to WinRT Database Project

I mentioned months before my WinRT database project.  I was going to stop working on it, but unfortunately as of now there is no good alternative to structured storage in WinRT applications.  SQLite team is working on WinRT version, but there is no projected date as far as I know.

So, upon some thinking I decided to maintain the project.  I took time to update the code to Windows 8 Consumer Preview and VS 11 beta.  I added unit test project with basic tests and a sample project called WinRTDbQuickStart to the solution on CodePlex.  If you download source code, you can get a quick tutorial by looking at the sample project.

I added a utility class to help with data binding.  It can serve as base class for your object that you store in database.  Here is full code for the helper class:

using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace WinRTDatabase
{
    /// <summary>
    /// Base class for objects that can be put inside tables
    /// </summary>
    public class PropertyChangedCore : INotifyPropertyChanged
    {
        /// <summary>
        /// Set property value
        /// </summary>
        /// <typeparam name="T">Type of property</typeparam>
        /// <param name="value">New value</param>
        /// <param name="backingField">Backing field for property</param>
        /// <param name="propertyName">Name of property, leave blank</param>
        protected void SetProperty<T>(T value, ref T backingField, [CallerMemberName] string propertyName = "")
        {
            if (backingField == null && value != null)
            {
                backingField = value;
                OnPropertyChanged(propertyName);
            }
            else if (backingField != null && value == null)
            {
                backingField = value;
                OnPropertyChanged(propertyName);
            }
            else if (backingField != null && value != null && !backingField.Equals(value))
            {
                backingField = value;
                OnPropertyChanged(propertyName);
            }
        }

        /// <summary>
        /// Property changed event
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Raises <see cref="PropertyChanged"/> event/>
        /// </summary>
        /// <param name="propertyName">Name of property to raise event for</param>
        protected void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

The code is similar to template that is used in Metro style applications project templates distributed with VS 11.  However, I made an enhancement to it, comparing old value with new value for each property, and only raising property changed event if new value is different.  I had to do that because I ran into an issue with data binding, when property setter was invoked by data binding, event though nothing was changed.  Maybe it is a but in WinRT?

There is also facility that maintains state in database, so that you always check IsDirty flag on database to find out if you need to save.  I demonstrate the use of that property in my sample project by disabling Save button.

Most interesting code is in ViewModel class.  Here is the code for it.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WinRTDatabase;

namespace WinRTDbQuickStart
{
    public class MainViewModel : PropertyChangedCore
    {
        public string DatabaseName = "TestDb";
        private Database _database;

        public MainViewModel()
        {
            DeleteCommand = new SimpleCommand<Person>(OnDelete);
            AddCommand = new SimpleCommand<Person>(OnAdd, CanAdd);
            SaveCommand = new SimpleCommand<object>(OnSave, CanSave);
            Initialise();
        }

        public async void Initialise()
        {
            //await Database.DeleteDatabase(DatabaseName, StorageLocation.Local);
            var exists = await Database.DoesDatabaseExistsAsync(DatabaseName, StorageLocation.Local);
            if (!exists)
            {
                _database = await Database.CreateDatabaseAsync(DatabaseName, StorageLocation.Local);
                _database.CreateTable<Person>();
                var table = await _database.Table<Person>();
                await _database.SaveAsync();
                People = table;
            }
            else
            {
                _database = await Database.OpenDatabaseAsync(DatabaseName, true, StorageLocation.Local);
                People = await _database.Table<Person>();
            }

            SaveCommand.RaiseCanExecuteChanged();
            AddCommand.RaiseCanExecuteChanged();
            if (People.Count > 0)
            {
                SelectedPerson = People.First();
            }
            _database.PropertyChanged += new PropertyChangedEventHandler(_database_PropertyChanged);
        }

        void _database_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            SaveCommand.RaiseCanExecuteChanged();
            AddCommand.RaiseCanExecuteChanged();
        }

        private Table<Person> people;

        public Table<Person> People
        {
            get { return people; }
            set
            {
                people = value; OnPropertyChanged("People");
                if (people.Count > 0)
                {
                    SelectedPerson = people.First<Person>();
                }
            }
        }

        private Person selectedPerson;

        public Person SelectedPerson
        {
            get { return selectedPerson; }
            set
            {
                selectedPerson = value;
                OnPropertyChanged("SelectedPerson");
            }
        }

        public SimpleCommand<Person> DeleteCommand { get; set; }

        public void OnDelete(Person parameter)
        {
            if (parameter != null)
            {
                People.Remove(parameter);
                if (People.Count > 0)
                {
                    SelectedPerson = People.First();
                }
            }
        }

        public SimpleCommand<Person> AddCommand { get; set; }

        public void OnAdd(Person parameter)
        {
            People.Add(new Person { PersonID = Guid.NewGuid(), FirstName=" ", LastName = " " });
            SelectedPerson = People.Last();
        }
        public bool CanAdd(object parameter)
        {
            return (_database != null && People != null);
        }

        public SimpleCommand<object> SaveCommand { get; set; }

        public void OnSave(object parameter)
        {
            if (_database != null)
            {
                _database.SaveAsync();
            }
        }
        public bool CanSave(object parameter)
        {
            return (_database != null && !_database.IsBusy && _database.IsDirty);
        }
    }
}

 

Code is pretty simple, although I wrote a simple command to help me along that implements ICommand.

using System;
using System.Windows.Input;

namespace WinRTDbQuickStart
{
    public class SimpleCommand<T> : ICommand
    {
        private Action<T> _executeMethod;
        private Func<T, bool> _canExecuteMethod;

        public SimpleCommand(Action<T> executemethod, Func<T, bool> canExecuteMethod)
        {
            _executeMethod = executemethod;
            _canExecuteMethod = canExecuteMethod;
        }

        public SimpleCommand(Action<T> executemethod)
        {
            _executeMethod = executemethod;
        }

        public bool CanExecute(object parameter)
        {
            if (_canExecuteMethod == null)
            {
                return true;
            }
            else
            {
                return _canExecuteMethod((T)parameter);
            }
        }

        public event EventHandler CanExecuteChanged;
        protected void OnCanExecuteChanged()
        {
            if (CanExecuteChanged != null)
            {
                CanExecuteChanged(this, EventArgs.Empty);
            }
        }

        public void Execute(object parameter)
        {
            _executeMethod((T)parameter);
        }

        public void RaiseCanExecuteChanged()
        {
            OnCanExecuteChanged();
        }

    }
}

As you can see, I am binding ListBox control directly to the data stored in a table.

Another important thing to notice.  All store and retrieve operations as async.  You need to make sure you are following this pattern and are using await keyword as needed.

Please let me know if you have any questions or suggestions.

Thanks.

Post to Twitter

Code Mastery event in Boston

As you may know, Magenic has been putting on Code Mastery events for quite some time.  This is a free event, similar to Code Camp, but is put on by our company,   We do it every year in all the cities where Magenic has an office.  Code Mastery events are designed to present attendees with meaningful technical content by the professionals that are using them every day, in the trenches.

Our Boston event is coming up soon.  Check out the details on Code Mastery site

http://codemastery.com/boston/

Post to Twitter

More on WinDbg, Memory Leaks and Silverlight

I blogged a long time ago on how to use WinDbg to find memory leaks in Silverlight application.  Yesterday I had to face a variation of the problem, but this time I had to debug a custom issue.  So, what we did is have customer create memory dumps.  To do that we instructed them to run the application in IE, what periodically for memory used by IE, then when memory got unreasonably high, take memory dump.  You can do that from Task Manager.  Just right-click on your process (iexplore.exe), and select option Create Dump File.  Once that is done, just have your customer transfer the file to you.

Once you have it on your local hard drive, start WinDbg (32 bit version) and under File menu select Open Crash Dump and point to your file.  Once thing you must have is the same version of Silverlight as they use.  If you do not, find a machine that has that version and copy the content of C:\Program Files (x86)\Microsoft Silverlight\{target version} onto your machine into the same folder.  You may have to use C:\Program Files\Microsoft Silverlight if the customer is running 32 bit OS because the dump file will refer to that path.

Once that is done, in command line window (bottom of WinDbg screen) type

.load C:\Program Files (x86)\Microsoft Silverlight\4.1.10111.0\sos.dll

where the path you use is the one containing the same version of Silverlight.

Once that is done, you need to load CLR debugging modules

.cordll -ve -u –l

You may also need to expand search path for WinDbg to find debugging symbols

.exepath+ C:\Program Files\Microsoft Silverlight\4.1.10111.0\

After that you are ready to run

!dumpheap -stat

Then continue as described in my previous post.  What have we achieved here you ask?  I just implemented remote debugging on client machine!  Pretty cool, hah?

Thanks.

Post to Twitter

More on jqGrid and getRowData function in edit mode

I blogged a while back on shortcoming of getRowData function of jqGrid in edit mode.  I also recently ran into an issue when getRowData was returning blank for a cell that contains select (dropdown) control in edit mode.  So, I wrote a quick function that I wanted to post here to help others that handles both situations (the best it can in the case of a blank).

 

window.jqHelpers = window.jqHelpers ||
{
    parseValueFromJQGridCell: function (celValueReturndByGetRowData, columnName, handleBlanks) {
        var controlNameToLookFor = new RegExp("id=\".+_" + columnName, "ig");
        var finalValue = celValueReturndByGetRowData;
        if (celValueReturndByGetRowData.toLowerCase().indexOf('<input') >= 0 || celValueReturndByGetRowData.toLowerCase().indexOf('<select') >= 0) {
            var matched = finalValue.match(controlNameToLookFor)[0];
            var rowIndex = matched.toUpperCase().replace("ID=\"", "").replace("_" + columnName.toUpperCase(), "");
            finalValue = $('#' + rowIndex + '_' + columnName).val();
        };
        if (!finalValue && handleBlanks) {
            var inputControl = $('input[id*=' + columnName);
            if (inputControl.length) {
                finalValue = inputControl.val();
            }
        }
        if (!finalValue && handleBlanks) {
            var selectControl = $('select[id*=' + columnName);
            if (selectControl.length) {
                finalValue = selectControl.val();
            }
        }
        return finalValue;
    }
}

The idea is that after you call getRowData, you would run through the returned array and only for columns that are editable call the function, such as

oneRow['ColumnName'] = jqHelpers.parseValueFromJQGridCell(oneRow['ColumnName'], 'ColumnName', true);

Enjoy.

Post to Twitter

TransactionScope and Connection Pooling in SQL Server

There is one very interesting behavior of connection pooling feature in .NET framework / SQL Server that I learned yesterday.  You can read the Connect issue here.  Interestingly enough, default setting for TransactionScope object is to use Serializable Isolation Level.

Here is a typical scenario to put the problem in perspective.

  • An application is using connection pooling and SQL Server.  Connection pooling of course greatly improves performance of connecting to SQL Server and is enabled by default in SQL Connection.
  • An application is using TransactionScope to handle transactions.
  • You fired an UPDATE operation via TransactionScope
  • Another user is firing a SELECT statement.  At that time a connection is retrieved from connection pool and happens to be the same connection that the UPDATE statement used.
  • Result – your SELECT statement is executed with Serializable isolation level, acquiring exclusive locks.  So the data you just read is not accessible to any other user until your transaction (that you do not even need) completes, likely when you are done reading your data and close the connection.

In application with a few users this is not really an issue.  Anyone who is designing an application for high availability must account for this behavior however.

Post to Twitter

Performance Considerations for Entity Framework 5

If you are wondering how many cool features are coming in Entity Framework 5.0, the EF team wrote an awesome white paper on performance improvements and tips to get the best performance out of EF.  Please read the article here.

To me this article proves a great commitment that Microsoft as a company has to Entity Framework technology.  It is apparent that they not only add features to the technology, but also are very much interested in improving existing functionality as well.  You can read more about EF 5 on ADO.NET Team Blog.

Great work, EF team.

Post to Twitter

More on Refactoring in SSDT

I wanted to make a few more points about using SSDT in addition to previous posts.  As I was working on my project, I wanted to drop a procedure that was no longer used, but there is nothing on re-factor menu to support that.  Come to find out, you have to follow a different pattern of development.  For example, I added a History table in my previous example:

image

I can deploy my solution to create this new table.  By the way, if I have multiple publish profiles (*.publish.xml files), I can pick a default one by right clicking on it, then selecting Set as Default Publish Profile option.  From that point on, if you right-click on project and select Publish option, this default profile will be automatically selected for you.

Coming back to dropping object, now I decide I do not want this History table any longer.  Now, I just delete the file from project first.  If I deploy again, I will see that the table is not dropped from target database.  What I need to do now is go to project properties, select Debug menu and check the option called DROP objects in target but not in project.

image

 

Now, let’s publish again.  The table is still there?..  Well, there is one more place I must modify.  I am going to select publish option again, but this time I click Advanced… button.

image

On the following screen I need to check the option called DROP objects in target but not in project one more time. Then, I click on Save As button and re-select the same .publish.xml file to overwrite that profile.

image

Now, I just publish one more time.  Voila, the table is now gone.  The same procedure can be used now to drop all the objects no longer used.

Thanks.

Post to Twitter

VS Live 2012 Las Vegas

I presented on two topics on Tuesday 3/27/2012 at VS Live conference in Las Vegas.

Entity Framework Code First – Beyond the Basics

This session cover scenarios beyond the basics of EF Code First usage. Topics such as creation of object hierarchies and complex types will be discussed. Performance tips will be covered as well as usage scenarios in services. Techniques to handle schema changes will be discussed. High level overview of how to handle various RDBMS with Entity Framework will be part of the conversation.

You can download Power Point presentation here and sample project here.

 

Building Data Driven Applications Using WinRT and XAML

This session will help attendees understand data access techniques in WinRT. The talk will highlight various ways to persists the data locally and via services. Topics will include data binding implications in regard with data usages, asynchronous access to data, and binding to various XAML controls.

You can download Power Point presentation here and sample project here.

Thank you.

Post to Twitter

Update to Windows Phone 7 Controls

I updated Calendar control for Windows Phone 7 on CodePlex today.

I added support for other languages as well as published the package to NuGet.

You can added it to your Windows Phone 7 applications, both targeting 7.0 and 7.1 versions by typing the following into NuGet package manager console: Install-Package WPControls

You can also see package details at https://nuget.org/packages/WPControls

I wanted to illustrate right quick how I added support for other languages.  There are only a few things I have to localize: week day names and month names.  It happens, that both are very easy to do through DateTimeFormat object.

Here is how I am setting week day names:

            _dateTimeFormatInfo = !CultureInfo.CurrentCulture.IsNeutralCulture ?
                CultureInfo.CurrentCulture.DateTimeFormat :
                (new CultureInfo("en-US")).DateTimeFormat;

I have to protect against neutral cultures, so I am using en-US as default for those.

        private void SetupDaysOfWeekLabels()
        {
            Sunday = _dateTimeFormatInfo.AbbreviatedDayNames[0];
            Monday = _dateTimeFormatInfo.AbbreviatedDayNames[1];
            Tuesday = _dateTimeFormatInfo.AbbreviatedDayNames[2];
            Wednesday = _dateTimeFormatInfo.AbbreviatedDayNames[3];
            Thursday = _dateTimeFormatInfo.AbbreviatedDayNames[4];
            Friday = _dateTimeFormatInfo.AbbreviatedDayNames[5];
            Saturday = _dateTimeFormatInfo.AbbreviatedDayNames[6];
        }

 

As you can see this is very easy to do.  I am making my week start on Sunday and in my control template I use TemplateBinding to point to my Sunday through Saturday properties.

Month name is just as easy.

        private string GetMonthName()
        {
            string returnValue = _dateTimeFormatInfo.MonthNames[_month - 1];
            return returnValue;
        }

My _month variable contains month number 1 through 12.

That is all there is to it.

Enjoy and please continue providing feedback for Calendar control.

Thanks.

Post to Twitter

Refactoring with SSDT

In my previous post I gave an overview of SSDT, SQL Server Data Tools.In this post I will give some hints on refactoring of the data structures. 

One of the common refactoring actions is a column rename. Let’s take a look at that.  Open a table in design view by double-clicking on it solution explorer.  Your view should look similar to the following.

image

There is no obvious menu that supports renaming.  Just click on a column in the T-SQL Pane, right click on it, then choose Refactor sub-menu, then Rename menu item.

image

Next screen will allow you to change the name of the column

image

Now just publish to local database, and you are set to go.  So, how does this magic work?  You will see a file with your project name and extension refactorlog in your project now.  Just open it, and you will see how renaming is handled in database projects.

<?xml version="1.0" encoding="utf-8"?>
<Operations Version="1.0" xmlns="http://schemas.microsoft.com/sqlserver/dac/Serialization/2012/02">
  <Operation Name="Rename Refactor" Key="4bdbbf1f-6154-4129-9e42-3b904570cd7c" ChangeDateTime="03/17/2012 20:10:47">
    <Property Name="ElementName" Value="[dbo].[Assignment].[Assigned]" />
    <Property Name="ElementType" Value="SqlSimpleColumn" />
    <Property Name="ParentElementName" Value="[dbo].[Assignment]" />
    <Property Name="ParentElementType" Value="SqlTable" />
    <Property Name="NewName" Value="[AssignedDate]" />
  </Operation>
</Operations>

The same procedure applies when you rename the table.  Just right click on a table name in T-SQL pane.

Pretty easy, right?

If you take a closer look at the refactoring menu, you will see other useful actions, especially if you are working with stored procedures.  For example, let me add a stored procedure that select all columns from Assignment table above.

I am going to add a folder, called procedures to my project, then add new stored procedure item using Add New Item menu.

I am going to start as following.

CREATE PROCEDURE [dbo].[SelectAllAssignments]

AS
    SELECT *
    From Assignment
RETURN 0

Then, I right click on * symbol, select Refactor, then Expand Wildcards

image

Now, just click Apply.

You can also choose option to Fully Qualify Names:

image

The last option is to move objects to a different schema.  To accomplish that, I first create new schema called users.

CREATE SCHEMA [users]

Of course, this is also an item in my project.  Then I can edit my stored procedure and select move to schema refactoring

image

My new schema was available from drop down already.  My refactorlog file was updated accordingly.  Now publish to test the changes.

I hope this gives you a taste of refactoring functionality in SSDT.

Enjoy.

Thanks.

Post to Twitter

Getting Started with SQL Server Data Tools (SSDT)

As you know, I have been working for Magenic for over 5 years now.  One of the initiatives that we have at our company is to have company blog in addition to many consultants having their own blogs.  You can check out Magenic company blog here.

I recently wrote a post on SQL Server Data Tools that was just published on Magenic blog. Enjoy the light reading.

Thanks.

Post to Twitter

We’re hiring at Magenic!

.NET Consultant – Atlanta | Atlanta, GA

Magenic is offering full-time salaried opportunities for .NET developers to join our Atlanta team.  We are looking for talented people with a passion for Microsoft technology who have developed .NET applications on the Microsoft stack of tools.

clip_image002[6]

Learn more  |  Apply now  |  Forward this job

Post to Twitter

2012 for Microsoft Developers

In this post I want to summarize the tools and technologies that will be coming up in 2012 from Microsoft.  All of these is public knowledge, but I wanted to outline the technologies that excite me the most.  There are some conjectures and opinions of course, and some educated guesses.  I am going to include relevant links for you to try those technologies.  All comments are greatly welcomed.

Let’s start with the operating system.  Windows 8 Consumer preview was released last week.  Here is the main page for Windows 8 at Microsoft.com   You can download an ISO image of the operating system.  I opted to install it as a virtual hard drive, following these great instructions from Eric Boyd.  Once you run through the steps, you will see an additional boot menu, where you can choose which OS you would like to run – Windows 7 or Windows 8.  I have used Windows 8 now for a few days, and it seems to be very stable to me.  There are a few apps in the app store you can download and play with.  I really liked Weather app.  It seems very intuitive and works well.  Other apps, including those from Microsoft seems to be lacking a bit IMHO.  Beta version, you know.  If you are using Windows 8 on non-touch enabled laptop, here is a list of helpful keyboard shortcuts.  As far as the release date goes, nothing has been announced yet, but it stands to reason it will be out in time for holiday season this year.  It just makes sense, since preview (beta) is out already.

Next is Visual Studio 11.  Since it has features to build Metro style applications for Windows 8, it must be released with Windows 8.  Hence, it should be out this year.  You can download the ISO here and install it on your brand spanking new Windows 8 beta image.  I have used it for 4 days now since it was released last week.  It also seems to be quite stable on my VHD based image.  It seems snappy and I have not found any issues.  You have to get used to grey-scale environment.  I thought I would not like the lack of colors, but I stopped noticing that very quickly.  There are Metro apps (windows 9 store apps) templates that ship with the Visual Studio.  I have to comment on greatly increased quality of those templates, as it compares with preview version that shipped last year.  it is quite obvious that Microsoft has put a ton of effort into the studio since preview.  A number of issues, mainly dealing with data binding, that I blogged about last year, no longer exist.  Visual Studio itself has a lot of improvements.  There are improvements to CSS editor, JavaScript editor and HTML editor,  There are also core .NET framework features, such as async / await keywords will be available, making asynchronous programming model much cleaner.  There are enhancements to web development, such as web sockets support, bundling and minification of scripts, support for asynchronous modules and handlers.  Also, Blend is shipping with VS 11.  It now supports HTML applications in addition to XAML based applications.

MVC 4.0 Beta is out as well.  You can download it here.  There are versions for VS 2010 and VS 11 beta.  The feature list is very long and you can read it here.  I am going to mention my favorite ones.  Number one I think is Web API, an alternative to WCF.  You can now have light weight communication API that is using full power of HTTP.  Yet, it has many feature that still provide powerful abstractions, making it easy for developers to use it as an alternative to WCF (REST or SOAP).  Next, I really like that Microsoft embraced mobile web as core part of web development today.

it would be a shame not to mention SQL Server 2012.  Here are some features I like:

Paging T-SQL (OFFSET and FETCH).  Those keywords essentially map to Skip and Top statements in Linq.  AN example would be

Select Person.ID, Person.Name

From Person

Where Name LIKE ‘%a%’

Order By Name

OFFSET 25 ROWS

FETCH NEXT 25 ROWS ONLY

Now instead of crazy paging code you have clean and optimized queries.

There are also sequences (as an alternative to IDENTITY columns), PowerPivot enhancements, Project Crescent (Web based visualization), Data Quality Services, etc…

One feature that excites me a ton is SSDT (SQL Server Data Tools).  This is the replacement for Data Dude (Database projects in Visual Studio).  I am loving the new features and clean integration into Visual Studio as well as great support for Azure development and deployment and MS Build integration.  The install itself is fully integrated into Web Platform Installer (WebPI).

Also, entity framework version 5 will likely ship this year, as it is using enhancements to .NET 4.5.  It will have support for enumerations and spatial types, as well as performance improvements.

All-and-all, there is a lot of products, each with a ton of features, to numerous to count, that will be coming (as I am guessing) this year.  I am quite excited about these new release,s and am already learning the new features. 

Thank you.

Post to Twitter

Incrementing Version from TFS Build

I was working on an automated build for TFS the other day.  One of the tasks I was trying to accomplish is automatically increment version number as part of the build.  There is no build task I could use, so I wrote a little utility to do so and plugged into the build.  I am going to document the process in this blog.

First step is to minimize the effort by employing the following scheme in my solution.  By default, assembly version and assembly file version are included in AssemblyInfo.cs in each project in the solution.  Whenever I setup a brand new solution, I always move those attributes out of each project and add them to SolutionInfo.cs file.  Then, I include this file in every project via add as link option in Add Existing Item dialog.  This way I only need to increment this version in a single file in my build.  The code I need to modify looks as follows:

[assembly: AssemblyVersion("4.3.2.1")]
[assembly: AssemblyFileVersion("4.3.2.1")]

My utility just bumps up the last number (build number in this case).  The utility is very simple.  It is just a console application with two methods:

 class Program
    {
        static void Main(string[] args)
        {
            if (args.Length == 1)
            {
                var fileContent = System.IO.File.ReadAllLines(args[0]);
                var counter = 0;
                foreach (var line in fileContent)
                {
                    var currentLine = line;
                    if (currentLine.Contains("[assembly: AssemblyVersion("))
                    {
                        fileContent[counter] = UpdateVersion(line);
                    }
                    else if (line.Contains("[assembly: AssemblyFileVersion("))
                    {
                        fileContent[counter] = UpdateVersion(line);
                    }
                    counter++;
                }
                System.IO.File.WriteAllLines(args[0], fileContent);
                Environment.ExitCode = 0;
                return;
            }
            else
            {
                Console.Write("One argument is required");
                Environment.ExitCode = -1;
                return;
            }
        }
        private  static  string UpdateVersion(string line)
        {
            string currentLine = line;
            int lastPeriodPosition = line.LastIndexOf(".");
            int lastQuotePosition = line.LastIndexOf("\"");
            int currentVersion = int.Parse(currentLine.Substring(lastPeriodPosition + 1, lastQuotePosition - lastPeriodPosition - 1));
            currentLine = line.Substring(0, lastPeriodPosition + 1) + (currentVersion + 1).ToString() + line.Substring(lastQuotePosition);
            return currentLine;
        }
    }

A couple of things to notice.  I added Exit Codes everywhere in order to know that an error has occurred as part of the utility execution inside the build process.  Now with utility out of the way, it is time to add some tasks to my build.

I am going to use TF.exe utility that is part of TFS / Visual Studio installer.  It is a command line utility that allows the user to perform basic TFS functions.  In my case, I need checkout and checkin functions.  You can read more about TF.exe on MSDN http://msdn.microsoft.com/en-us/library/cc31bk2e(v=vs.80).aspx

Now, let’s look at the TFBuild.proj file.  I am setting up properties pointing to my TF.exe first.  I have to quote it because the path has spaces in it.  I am adding the location to PropertyGroup section

    <PropertyGroup>
        <TF>&quot;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\TF.exe&quot;</TF>
        <VersionUtilityExecutable>VersionUtility.exe</VersionUtilityExecutable>
        <SolutionInfoFile>SolutionInfo.cs</SolutionInfoFile>
    </PropertyGroup>

 

As you can see, I also added SolutionInfo property and my Updater executable property.  Then I need to call the TF and my updater utility after the latest has been retrieved from TFS.  I am using AfterGet target.

    <Target Name="AfterGet">
        <Exec WorkingDirectory="$(SolutionRoot)\MySolution" Command="$(TF) checkout $(SolutionInfoFile)" ContinueOnError="false"/>
        <Exec WorkingDirectory="$(SolutionRoot)\Build\"
            Command="&quot;$(SolutionRoot)\Build\$(VersionUtilityExecutable)&quot; &quot;$(SolutionRoot)\MySolution\$(SolutionInfoFile)&quot;" ContinueOnError="false"/>
    </Target>

SolutionRoot is my TFS project root, and MySolution is the location of the solution under the root TFS project folder.  While we are at it, I need to remember that if an error occurs, I need to undo check out.  I am doing this in BeforeOnBuildBreak target

    <Target Name="BeforeOnBuildBreak">
        <Exec WorkingDirectory="$(SolutionRoot)\MySolution" Command="$(TF) undo /noprompt $(SolutionInfoFile)" ContinueOnError="false"/>
    </Target>

 

Now after the build I need to call my utility and check the SolutionInfo.cs file back in.  I am doing it in AfterCompile target.

    <Target Name="AfterCompile">
        <Exec WorkingDirectory="$(SolutionRoot)\MySolution" Command="$(TF) checkin /comment:&quot;Build version update&quot; /noprompt /override:&quot;Build version update&quot; $(SolutionInfoFile)" ContinueOnError="false"/>
    </Target>

And there is all there is to.  You can read more about targets inside TFS build here. http://msdn.microsoft.com/en-us/library/aa337604(v=vs.80).aspx

Also, I recommend you add Message commands to log into the build log. The same applies to utility. All Console.Write commands will end up in your build log as well.

Thanks.

Post to Twitter

Getting Started with SSRS on Azure

In this post I will describe how to get started with running SQL Server Reporting Services on Azure.  SSRS on Azure is now in beta stage, but anyone can give it a whirl. 

First of all, activate the service and create new report server.  When you are on management portal, click on Reporting link (see below).

Now click on the following button

Now pick subscription and server location.  Try to pick it to be in the same data server as your SQL Azure database you will report on.

Now fill in user and password.  You will need this information later, so write it down.

Click finish to complete the setup.  You will see newly created server on the screen.  You will also need the url from the screen below.

 

Now I am going to create an ASPX page I will use to display reports in my MVC application that I will deploy to Azure.  It will use Azure database to store the data as well.  You can read more about MVC and SSRS in my previous post – http://dotnetspeak.com/index.php/2012/02/using-ssrs-in-asp-net-mvc-application/.  Here I am going to describe the differences from that solution.

One important thing to notice is that SSRS on Azure does not support Windows authentication, so we have to use credentials property of the SSRS ASPX control.  First, let’s take a look at the ASPX portion of the form.  It is pretty simple:

 

<%@ Register Assembly="Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
    Namespace="Microsoft.Reporting.WebForms" TagPrefix="rsweb" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="reportForm" runat="server">
    <asp:ScriptManager ID="ScriptManager1" runat="server">
    </asp:ScriptManager>
    <div>
        <rsweb:ReportViewer ID="mainReportViewer" AsyncRendering="false" runat="server" Width="840px" Height="700px">
        </rsweb:ReportViewer>
    </div>
    </form>
</body>
</html>

Code behind just needs to set credentials.  I do not want to hard-code them, so I am adding those to web.config, and I am just using Configuration Manager to get to those.

        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {

                mainReportViewer.ServerReport.ReportServerUrl =
                    new Uri(ConfigurationManager.AppSettings["ReportServerUrl"]);
                mainReportViewer.ServerReport.ReportPath =
                    string.Format(ConfigurationManager.AppSettings["ReportPath"], (data.ReportFileName));
                mainReportViewer.ProcessingMode = ProcessingMode.Remote;
                mainReportViewer.ShowParameterPrompts = false;
                mainReportViewer.ShowRefreshButton = false;
                mainReportViewer.ShowWaitControlCancelLink = false;
                mainReportViewer.ShowBackButton = false;
                mainReportViewer.ShowCredentialPrompts = false;
                string userName = ConfigurationManager.AppSettings["ReportServerUserName"];
                string password = ConfigurationManager.AppSettings["ReportServerPassword"];
                if (!string.IsNullOrEmpty(userName) && !string.IsNullOrEmpty(password))
                {
                    mainReportViewer.ServerReport.ReportServerCredentials =
                        new ReportServerCredentials
                            {
                                UserName = userName,
                                UserPassword = password
                            };
                }
                // set parameters if needed                
                mainReportViewer.ServerReport.Refresh();
            }
        }

My ReportServerCredentials class is super simple, and just needs to implement the interface report viewer expects.

using Microsoft.Reporting.WebForms;

namespace MyApp.Reports
{
    public class ReportServerCredentials : IReportServerCredentials
    {

        public string UserName { get; set; }
        public string UserPassword { get; set; }
        public bool GetFormsCredentials(out System.Net.Cookie authCookie, out string userName, out string password, out string authority)
        {
            authCookie = null;
            userName = UserName;
            password = UserPassword;
            authority = "";
            return true;
        }

        public System.Security.Principal.WindowsIdentity ImpersonationUser
        {
            get { return null; }
        }
        public System.Net.ICredentials NetworkCredentials
        {
            get { return null; }
        }
    }
}

The actual credentials are the same as the ones you set up initially when you created the SSRS Server instance.

 

Now, you have to create the actual reports, using the standard SSRS reports project.  The key difference is that you need to set SQL Server version in the properties of the project to SQL Azure.  Another thing that makes the whole process simple is to setup a Shared Data Source and setup credentials for it.  Those are the credentials you setup in SQL Azure when setting up the database, not the ones you used for SSRS Server, although you could use the same, one less thing to remember.  Then you can use the same data source for all your reports.  The reports themselves are exactly the same, no difference\ whatsoever between SSRS Azure and SSRS on Windows.  You can deploy to Azure by using the same Deploy menu, available when you right click on the project.  You will get prompted for your SSRS Azure credentials again at that time.  Once you deployed those and your web application, your reports should now work.  Please review my previous post on setting up web.config with an http handler for reports.

Thanks and enjoy.

Post to Twitter

Using SSRS In ASP.NET MVC Application

In this blog I will describe my ideas on how to integrate SQL Server reports in ASP.NET MVC applications.  I would like to have as seamless of an integration as possible given the constraints in place.  For example, the only web based report viewer for SSRS is the one that has been shipping with Web Forms (ASPX).  Now that we have problem statement down, let’s get on with a high level solution I would like to implement.

  • I would like to integrate reports into the existing application
  • I would like to show them in an overlay, not wanting to popup additional browser window and having to deal with popup issues in general
  • I would like to make the report viewing safe, trying to reveal as little as possible to the user or technical observer who could use Fiddler for example.

Here is high level outline of my answer to these issues

  • I will have a parameter values collecting view in MVC app
  • I will log the data about selected report into the database along with parameter values, using ajax call to my controller. 
  • I will associate that information with a GUID
  • Controller will return a url with the guid back to my java script method.  Then the method will popup jQuery dialog with an embedded iFrame and set its source to the url passed back from controller
  • I will pass that GUID as a query parameter to ASPX page that will host Web Form report viewer control.
  • I will have web form get the report information from the database along with parameters, then configure report viewer.

That is it.  Now, let’s see some code.

To log report request into the database we just need a couple of tables: request header and request parameters.  I am using entity framework code first, so my tables could look something like this:

    public class ReportRequest
    {
        public int ReportRequestId { get; set; }

        [StringLength(50)]
        public string ReportFileName { get; set; }

        public Guid UniqueId { get; set; }

        public ICollection<ReportRequestParameter> Parameters { get; set; }
    }

 

    public class ReportRequestParameter
    {
        public int ReportRequestParameterId { get; set; }

        [StringLength(50)]
        public string ParameterName { get; set; }

        public string ParameterValue { get; set; }

        [Required]
        public int ReportRequestId { get; set; }

        [ForeignKey("ReportRequestId")]
        public ReportRequest ReportRequest { get; set; }
    }

This part is pretty easy.  Let me now build report center screen that lists all the reports in the system and allows user to print a report.  To support this I just need to have a list of all reports in the system and their parameters.  Again, two tables will suffice.  In parameters table I need the following information:

  • Parameter name (title I will use in a view)
  • SSRS parameter name(s).  I can just separate them via a pipe for example.  This allows me to build complex parameter partial views that can return multiple parameters and their values.
  • Partial view I can use to get the data for a parameter.

So, my plan is to let a user select a report, then build a UI by looking at each parameter and building a partial view for it.  Here is an example of one of those partial views:

@model MyApp.Reports.ReportParameter
<div class="display-label">
    @Model.ParameterName
</div>
<div class="editor-field">
    <select id="@(Model.ReportParameterNames)" name="@(Model.ReportParameterNames)" style="min-width: 200px">
        <option value="1" selected="selected">Option 1</option>
        <option value="2">Option 2</option>
        <option value="3">Option 3</option>
    </select>
</div>

This builds a drop down list control with three options.  One key thing to notice is that I am using ID and name that corresponds to a parameter name,  I will later use it to build parameters.

Now the report center view (I am coming in with a report already selected) may look something like the following

 

@model MyApp.Reports.Report
@using (Html.BeginForm())
{
    @Html.HiddenFor(model => model.ReportID)
    @Html.HiddenFor(model => model.ReportFileName)
    foreach (var parameter in Model.ReportParameters)
    {
        { Html.RenderPartial(parameter.PartialViewName, parameter); }
    }
    <br/>
    <button id="runReportButton" >Report Preview</button>

<div id="reportPreviewDiv" style="display: none">
    <iframe id="reportViewFrame" width="100%" height="100%" ></iframe>
</div>
<script src="@Url.Content("~/Scripts/app.js")" type="text/javascript"></script> 

As you can see, I am building a form from multiple partial views, then I am using jQuery ajax to submit that to my controller:

reports: {
                submitReportRequest: function () {
                    $.ajax({
                        url: "/Report/RunReport",
                        type: "POST",
                        dataType: 'json',
                        data: $('form').serializeArray(),
                        success: function (data, textStatus, jqXhr) {
                            var closeButton = {};
                            closeButton[‘Close’] = function () {
                                $(this).dialog("close");
                                $("#reportViewFrame").attr("src", "about:blank");
                            };
                            $('#reportPreviewDiv').dialog({
                                autoOpen: true,
                                title: ‘Report Preview’,
                                width: 880,
                                height: 800,
                                modal: true,
                                resizable: true,
                                autoResize: false,
                                buttons: closeButton,
                                open: function (event, ui) { $("#reportViewFrame").attr("src", data); }
                            });
                        },
                        error: app.handleAjaxError
                    });
                    return false;
                }
            }

Report class in scripts above is simply following best practices for java script, using name spaces to separate all the functions.

Now my controller method looks something like this:

            [HttpPost]
            public JsonResult RunReport(ReportData formData)
            {
                Guid id = Guid.NewGuid();
                using (var context = new ReportContext())
                {
                    var reportRequest =
                    new ReportRequest
                    {
                        ReportFileName = formData.ReportFileName,
                        UniqueId = id
                    };
                    context.ReportRequests.Add(reportRequest);

                    foreach (var key in formData.Keys)
                    {
                        var parameter =
                              new ReportRequestParameter
                              {
                                  ParameterName = key,
                                  ParameterValue = formData[key],
                                  ReportRequest = reportRequest
                              };
                        context.ReportRequestParameters.Add(parameter);
                    }
                    context.SaveChanges();
                }

                return Json(string.Format("/Reports/ReportForm.aspx?r={0}", id.ToString()));
            }

My form data class that contains all the information submitted by the form.  I created a custom class for it and a custom model binder to automate some data binding and keep me from referring to context inside the controller.

        [ModelBinder(typeof(ReportDataModelBinder))]
        public class ReportData : Dictionary<string, string>
        {

            public int ReportID { get; internal set; }

            public string ReportFileName { get; internal set; }

        }

And here is the binder

    public class ReportDataModelBinder : IModelBinder
    {
        public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            var request = controllerContext.HttpContext.Request;
            var returnValue = new Program.ReportData();
            foreach (var key in request.Form.AllKeys)
            {
                if (key.StartsWith("@"))
                {
                    returnValue.Add(key, request.Form[key]);
                }
                else if (key == "ReportID")
                {
                    returnValue.ReportID = int.Parse(request.Form[key]);
                }
                else if (key == "ReportFileName")
                {
                    returnValue.ReportFileName = request.Form[key];
                }
            }
            return returnValue;
        }
    }

As use can see, I am following convention to start all report (RDL) parameters with an @ sign.  Now all the data submitted through he form that starts with it must be a parameter.  In general, using Model binders is highly encouraged in MVC applications because it gives you an ability to cleanly incorporate custom data that is sent from client to the server in any controllers to avoid writing the same code many times.

 

This ends the MVC portion of the solution.  Now, I just create a brand new ASPX page and add it to the project.  Just use Add New Item menu.  Once form is added, you must update the routes in your MVC applications to ignore things that end with .aspx.  You do so in global.asax

public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.IgnoreRoute("{resource}.aspx/{*pathInfo}");

            routes.MapRoute(
                    "Default", // Route name
                    "{controller}/{action}/{id}", // URL with parameters
                    new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
            );

        }

The form itself is pretty simple, it just has report viewer control in it:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ReportForm.aspx.cs" Inherits="MyApp.Reports.ReportForm" %>

<%@ Register Assembly="Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
    Namespace="Microsoft.Reporting.WebForms" TagPrefix="rsweb" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="reportForm" runat="server">
    <asp:ScriptManager ID="ScriptManager1" runat="server">
    </asp:ScriptManager>
    <div>
        <rsweb:ReportViewer ID="mainReportViewer" runat="server" Width="700px" Height="600px">
        </rsweb:ReportViewer>
    </div>
    </form>
</body>
</html>

Make sure to include ScriptManager – report viewer control needs it.  The code behind is just a simple, I am getting the report data and parameter data then setting up my control


       protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                var requestID = Request.QueryString["r"];

  ReportRequest request;

                using (var context = new ReportContext())                {    request = context.ReportRequests.Include("Parameters").Where(one => one.UniqueId == id).FirstOrDefault();                }


                mainReportViewer.ServerReport.ReportServerUrl =
                    new Uri(ConfigurationManager.AppSettings["ReportServerUrl"]);
                mainReportViewer.ServerReport.ReportPath =
                    string.Format(ConfigurationManager.AppSettings["ReportPath"], (data.ReportFileName));
                mainReportViewer.ProcessingMode = ProcessingMode.Remote;
                mainReportViewer.ShowParameterPrompts = false;
                mainReportViewer.ShowRefreshButton = false;
                mainReportViewer.ShowWaitControlCancelLink = false;
                mainReportViewer.ShowBackButton = false;
                mainReportViewer.ShowCredentialPrompts = false;
                var parametersCollection = new List<ReportParameter>();
                foreach (var parameter in request.Parameters)
                {
                    var parameterName = parameter.ParameterName;
                    if (parameterName.StartsWith("@"))
                    {
                        parameterName = parameterName.Substring(1);
                    }
                    parametersCollection.Add(new ReportParameter(parameterName, parameter.ParameterValue, false));
                }
                mainReportViewer.ServerReport.SetParameters(parametersCollection);
                mainReportViewer.ServerReport.Refresh();
            }
        }

Now, we have to add a Http handler to the web.config file:

    <system.webServer>
        <validation validateIntegratedModeConfiguration="false"/>
        <modules runAllManagedModulesForAllRequests="true"/>
        <handlers>
            <add name="ReportViewerWebControlHandler"
            preCondition="integratedMode"
            verb="*" path="Reserved.ReportViewerWebControl.axd"
            type="Microsoft.Reporting.WebForms.HttpHandler,
      Microsoft.ReportViewer.WebForms, Version=10.0.0.0,
      Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"
      />
        </handlers>

        </system.webServer>

Wow, that was a lot of steps, but you are not ready to run reports inside your MVC application.  There are a few enhancements I would also like to suggest

  • Delete report request data once it is retrieved.  This makes our approach more secure, where the same url cannot be used multiple times
  • Play with height / width.  You cannot use 100% height/width on the report control because this does not work properly in all the browsers.
  • Remove direct dependency on DbContext by introducing a service or a repository between forms and data.
  • You can probably refine ReportData class, maybe convert it into an object with a dictionary property.
  • You want to actually implement global error handler, I just left a stub in my script
  • You want to implement some sort of ‘please wait’ window while your ajax is running.

Enjoy and let me know what you think.

Post to Twitter

Continuous Integration with Azure from TFS Build

Recently I have been doing some TFS work.  One of the tasks I have completed was to implement automatic publishing to Azure from TFS build.  Our goal is to automate as much as possible to make it easy for QA to test as well as ensure that every night we have a fresh build for them ready.  In addition to that there are a few side benefits of this approach that I really like.  It is very much in line with agile methodology, ensuring that we have a shippable version of the software as often as possible.  In addition to that it is nice to test the final product in eventual production environment as often as possible and as early as possible.  With this, let’s dive into the solution.

Our software solution is a typical web application, using ASP.NET MVC, Enterprise Library Data Access blocks based DAL, stored procedures, business objects layer and services layer.   We use VS Database project to manage database changes and deploy to QA.  We use VS 2010 and TFS 2008.

I already wrote a TFSBuild.proj file that I use to publish to QA.  This build does the following tasks

  • Build the solution
  • Migrates the database using Visual Studio Database Project
  • Deploys the solution to QA web site on premises.

Our unit and integration tests are run by Continuous integration build, so we do not run unit tests as part of QA build.  I decided to use this QA build as my base. 

Everything I read about publishing to Azure from build ignored one important issue – what to do with the database.  Unfortunately, database project does not support publishing to Azure.  It is a sad fact give the importance Microsoft put on Azure.

I have been using Red Gate products for many years, almost 10 to be specific.  Red Gate SQL Compare to the rescue.  The newest version 10 has Azure support.  More specifically, it allows one to compare local SQL Server 200 R2 database to Azure SQL Server database and synchronize them. Cool.  So, here is the outline of my TFSBuild.proj file.  More specifically, here are the tasks at the high level.

Build Azure based solution.  I created the solution by copying existing solution, then adding Azure project to it.

  • Deploy database using database project to a SQL Server.
  • Use SQL Compare to synchronize this database with a database on Azure that was created at some point.  It can be just blank database, as SQL Compare will create the structure for us.
  • Create Post deployment script by combining all post deployment scripts from database project, using Script.PostDeployment.sql and its data as the guideline.  Run this script against Azure database using a utility.
  • Use Azure Cmdlets package from CodePlex to deploy package to Azure.

No, let’s dive into the details.

To deploy database project from TFS Build, you just need the following task in your proj file.

    <PropertyGroup>
        <TargetConnString>Data&#x20;Source=MyServer%3BUser&#x20;myUserID%3BPassword=myPassword</TargetConnString>

A few key things to notice.  You have to en


    <Target Name="AfterDropBuild">
        <Message Text="Starting to deploy database project"/>
        <MSBuild Projects="$(SolutionRoot)\MySolution\MyDatabaseProject\MyDatabase.dbproj"               Properties="TargetDatabase=AZURE_TEST;Configuration=Release;OutDir=$(DropLocation)\$(BuildNumber)\Release\;TargetConnectionString=$(TargetConnString);DeployToDatabase=true"               Targets="Deploy"/>
        <Message Text="Finished deploying database project"/>

code connection string, or you will get some errors.  You do have to add the property DeployToDatabase=true to your command line or it will not deploy.  You will see that the build does run successfully, just does not apply updates.

Now off to Azure synchronization.  I wrote a little command line utility I will call to do two tasks: synchronize with Azure SQL DB and run the scripts against it.  The code is very simple for this utility, it just launches SQLCompare.exe, which comes with Professional version of SQL Compare, then does some string parsing to create post deployment script and runs it in.  Here is what the method that synchronizes DB looks like:

        public static bool UpdateAzureDB(string logFileName)
        {
            var process = new Process();
            if (File.Exists(logFileName))
            {
                File.Delete(logFileName);
            }
            var commandLine =
                @" /db1:AZURE_TEST /p1:localPassword /u1:localUserID /s1:localServer /db2:AZURE_DB /p2:azurePassword " +
                @"/u2:azureUserID /s2:********.database.windows.net /exclude:user /exclude:role " +
                @"/r:" + logFileName + @" /rt:Simple /sync  /include:identical";
            var startInfo = new ProcessStartInfo(
                @"C:\Program Files (x86)\Red Gate\SQL Compare 10\SqlCompare.exe", commandLine);
            process.StartInfo = startInfo;
            process.Start();
            process.WaitForExit();
            return process.ExitCode == 0;
        }

A couple of imporant notes.  We have to know if the process scusseeds, so we are trapping return value.  SQLCOmpare will return non-zero value if something goes wrong.  We are also creating a log file just in case in HTML format.  We are excluding database users and roles, since I do not need to synchronize those.

Next step is to create data massaging.  We are following database project best practices.  We are breaking down data massaging into multiple scripts, then combining them in Script.PostDeployment.sql.  Here is an example of that script:

/*
Post-Deployment Script Template
--------------------------------------------------------------------------------------
 This file contains SQL statements that will be appended to the build script.
 Use SQLCMD syntax to include a file in the post-deployment script.
 Example:      :r .\myfile.sql
--------------------------------------------------------------------------------------
*/
:r .\Table1.Data.SQL
:r .\Table2.Data.SQL

My utility will accept the directory name where this file is located, will parse the file, and create one giant string with the content of all the sub-scripts.  Once that is done, it will use passed in connection string and will fire out the final script.  Again, code is pretty simple.

        public static void UpdateData(string folderName, string azureConnectionString)
        {
            var scriptData =
                File.ReadAllLines(string.Format(@"{0}\{1}", folderName, "Script.PostDeployment.sql"));
            var finalScript =
                (from line in scriptData
                 where line.StartsWith(":r")
                 select line.Substring(line.IndexOf(@"\") + 1))
                    .Aggregate("", (current, fileName) => current + File.ReadAllText(string.Format(@"{0}\{1}", folderName, fileName)));

            using (var connection = new SqlConnection(azureConnectionString))
            {
                connection.Open();
                using (var command = connection.CreateCommand())
                {
                    command.CommandType = CommandType.Text;
                    command.CommandText = finalScript;
                    var rowsAffected = command.ExecuteNonQuery();
                }
            }
        }

Now, I just have a wrapper utility that calls both methods in susccessing, traps errors and only returns zero if both methods execute properly.  I need this so that I can stop the build in case of non-zero exit code from my utility. To do so, I use Environment.Exit(0) or non-zero value in case of errors.  I also use Console.WriteLine,because this data will end up in the build log and will help me troubleshoot issues.  Now, I just need to call it from TFSBuild.proj:

    <PropertyGroup>
        <DatabaseUpdaterExecutable>UpdaterApp.exe</DatabaseUpdaterExecutable>
        <AzureConnectionString>"Data&#x20;Source=xxxxxxxx.database.windows.net%3BInitial&#x20;Catalog=AZURE_DB%3BPersist&#x20;Security&#x20;Info=True%3BUser&#x20;ID=remoteUserID%3BPassword=remotePassword"</AzureConnectionString>
        <AzureDeploymentReportFileLocation>C:\Temp\AzureDBReport.html</AzureDeploymentReportFileLocation>

 

        <Message Text="Working on Azure DB"/>
        <Message Text="Executable: $(SolutionRoot)\Deployment\$(DatabaseUpdaterExecutable)"/>
        <Message Text="PostDeploymentScriptLocation: $(SolutionRoot)\MySolution\MyDatabaseProject\Scripts\Post-Deployment"/>
        <Message Text="AzureConnectionString: $(AzureConnectionString)"/>
        <Message Text="AzureDeploymentReportFileLocation: $(AzureDeploymentReportFileLocation)"/>
        <Exec Command="&quot;$(SolutionRoot)\Deployment\$(DatabaseUpdaterExecutable)&quot; &quot;$(SolutionRoot)\MySolution\MyDatabaseProject\Scripts\Post-Deployment&quot; $(AzureConnectionString) $(AzureDeploymentReportFileLocation)" ContinueOnError="false"/>
        <Message Text="Finished working on Azure"/>

Now, deploying the solution to Azure.  I ran into an issue installing Cmdlets.  I was getting “No snapins are installed error” when running PowerShell.exe.  What I ended up doing is installing both 32 and 64 bit versions of Cmdlets.  You can do that by opening installPSCmdlets.cmd that will be in your scripts folder after you install Cmdlets from CodePlex, and running it in both 32 and 64 bit code path.  You can just manually set powerShellDir variable to both values and running it twice.  Then do the same with installPSSnapIn.cmd.  Of course, make sure you do all that on your build server

Now, let’s update TFSBuild.proj file.  Here is the command in it:

    <PropertyGroup>
        <PackageName>MySolutionAzure.cspkg</PackageName>
        <ServiceConfigName>ServiceConfiguration.Cloud.cscfg</ServiceConfigName>
        <HostedServiceName>myServiceName</HostedServiceName>
        <Thumbprint>XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX</Thumbprint>
        <SubscriptionID>XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX</SubscriptionID>
        <Slot>Production</Slot>
        <StorageName>myStorageServiceName</StorageName>
    <Target Name="AfterDropBuild">

        <Message Text="Copying Azure configuration file"/>
        <Copy SourceFiles="$(SolutionRoot)\Configuration\Azure\Web.config"
            DestinationFolder="$(SolutionRoot)\MySolution\MyWebProject" OverwriteReadOnlyFiles="true"/>

        <Message Text="Starting to build azure project for deployment"/>
        <MSBuild Projects="$(SolutionRoot)\MySolution\MyAzureProject\MyAzureProject.ccproj" Properties="Configuration=Release;OutDir=$(DropLocation)\$(BuildNumber)\Release\app.publish\;PackageForComputeEmulator=true;" Targets="Rebuild;Publish"/>
        <Message Text="Finished to build azure project for deployment"/>

        <Copy SourceFiles="$(SolutionRoot)\MySolution\MyAzureProject\bin\Release\app.publish\MyAzureProject.cspkg"
            DestinationFolder="C:\temp" OverwriteReadOnlyFiles="true"/>

        <Copy SourceFiles="$(SolutionRoot)\MySolution\MyAzureProject\bin\Release\app.publish\\ServiceConfiguration.Cloud.cscfg"
            DestinationFolder="C:\temp" OverwriteReadOnlyFiles="true"/>

        <Message Text="Starting to push package to Azure.  Package location follows"/>
        <Message Text="$(DropLocation)\$(BuildNumber)\Release\"/>

        <Exec WorkingDirectory="$(SolutionRoot)\Deployment\" ContinueOnError="false"
              Command=" $(windir)\system32\WindowsPowerShell\v1.0\powershell.exe -f AzureDeploy.ps1 C:\temp\ $(PackageName) $(ServiceConfigName) $(HostedServiceName) $(Thumbprint) $(SubscriptionID) $(Slot) $(StorageName)"/>

        <Message Text="Done pushing package to Azure"/>

There are a couple of changes I made to ps1 file though.  You can find that file in a ton of places on the internet.  They all have the same issues.

  • No error handling
  • No checking to see if a depolyment already exists
  • They do not return non-zero exit code to signal to build that deployment failed.

You have to address these issues for clean deployment.

Here is my version:

$buildPath = $args[0]
$packagename = $args[1]
$serviceconfig = $args[2]
$servicename = $args[3]
$thumbprint = $args[4]

$cert = Get-Item cert:\CurrentUser\My\$thumbprint
$sub = $args[5]
$slot = $args[6]
$storage = $args[7]
$package = join-path $buildPath $packageName
$config = join-path $buildPath $serviceconfig
$a = Get-Date
$buildLabel = $a.ToShortDateString() + "-" + $a.ToShortTimeString()

write-host  "parameters"
write-host  $args[0]
write-host  $args[1]
write-host  $args[2]
write-host  $args[3]
write-host  $args[4]
write-host  $args[5]
write-host  $args[6]
write-host  $args[7]
write-host  "package data"
write-host  $package
write-host  $config
write-host  $servicename

#Important!  When using file based packages (non-http paths), the
#cmdlets will attempt to upload the package to blob storage for
#you automatically.  If you do not specifiy a –
#StorageServiceName option, it will attempt to upload a storage
#account with the same name as $servicename.  If that
#account does not exist, it will fail.  This only applies to
#file-based package paths.
$exitCode=0
Try
{
    $ErrorActionPreference = "stop"

    Add-PSSnapin WAPPSCmdlets
    Try
    {
        $hostedService = Get-HostedService $servicename -Certificate $cert -SubscriptionId $sub | Get-Deployment -Slot $slot

        if ($hostedService.Status -ne $null)
        {
            $hostedService |
              Set-DeploymentStatus 'Suspended' |
              Get-OperationStatus -WaitToComplete
            $hostedService |
              Remove-Deployment |
              Get-OperationStatus -WaitToComplete
        }
    }
    Catch
    {
        # eat errors as we may not have an active deployment
    }

    Get-HostedService -ServiceName $servicename -Certificate $cert -SubscriptionId $sub | New-Deployment -Slot $slot -Package $package -Configuration $config -Label $buildLabel -ServiceName $servicename -StorageServiceName $storage |
        Get-OperationStatus -WaitToComplete

    Get-HostedService -ServiceName $servicename -Certificate $cert -SubscriptionId $sub |
        Get-Deployment -Slot $slot |
        Set-DeploymentStatus 'Running' |
        Get-OperationStatus -WaitToComplete
}
Catch
{
    $exitCode=-1
    write-host $error
}
exit $exitCode

I also added a few more thing.  I echo to the build some important information, which makes it much easier to debug the problems when they occur

To do initial push, I recommend you you Publish feature from studio, as it will handle all the myriad of certificates you need to get right to publish from the power shell.

Make sure you pick correct certificate for deployment.  If you are looking at your Windows Azure management console, you need the one listed under Management tab.  Look at the thumbprint, then find it on the machine that you did initial push for. I recommend using management console in Windows.  Type “mmc” in Start->Run.  Then add a Certificates Snap in, find it under the very first node, export it to PFX file using mmc, then import it on Build machine after you login with the same account your build runs under.  While on the subject, you should install ALL required software under that account just in case.  This includes Azure SDK, which you will need, and other dependencies from Cmdlets, etc…

Now, just schedule your build, and you are ready to go.

Post to Twitter

CSLA 4 version 4.3.0 alpha available

Rocky Lhotka published alpha version of CSLA 4.3 last week.  You can read more about the changes on his blog.  If you are using CSLA 4.X with Silverlight, please give this version a try.  If you are using an order version, 3.8.X, you can easily port the changes over to that version.  Or you can just upgrade to 4.3 Smile.

Please let me know if you have any questions.

Thanks.

Post to Twitter

Creating WCF Service with SOAP/REST Endpoints

In this post I am going to describe a solution to the following problem.  I would like to create a single WCF Service and expose it via a standard SOAP endpoint and REST endpoint using Entity Framework, WCF and WCF REST.  Then I would like to consume it from WinRT from two different view models working against the same view.  This is an exercise of research into data options in WinRT.

First of, let’s create a service.  I am going to use the following data class:

    public class Session
    {
        public int SessionID { get; set; }
        public string Title { get; set; }
        public string Description { get; set; }
        public string Speaker { get; set; }
        public DateTime When { get; set; }
    }

My data context for EF Code First is just as simple:

    public class Context : DbContext
    {
        public Context() :
            base("Name=VSLive")
        {
        }
        public DbSet<Session> Sessions { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Entity<Session>().Property(p => p.Title).HasMaxLength(100).IsRequired();
            modelBuilder.Entity<Session>().Property(p => p.Speaker).HasMaxLength(50).IsRequired();
            modelBuilder.Entity<Session>().Property(p => p.Description).IsRequired();
            modelBuilder.Entity<Session>().Property(p => p.When).IsRequired();
        }
    }

Now, the service.  I am just going to perform basis CRUD opertions.  The key to the service is my interface that I am going to decorate with both SOAP(OperationContract) and REST(WebGet or WebInvoke) attributes.

    [ServiceContract]

    public interface IVSLiveService
    {
        [OperationContract]
        [WebGet(UriTemplate = "/GetList", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
        Session[] GetList();

        [OperationContract]
        [WebInvoke(UriTemplate = "/Create", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
        Session Create(Session session);

        [OperationContract]
        [WebInvoke(UriTemplate = "/Update", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
        Session Update(Session session);

        [OperationContract]
        [WebInvoke(UriTemplate = "/Delete?sessionId={sessionId}", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
        void Delete(int sessionId);

    }

The implementation is not quite as interesting, but for the same of completeness of this post, here it goes:

using System.Data.Entity;
using System.Linq;
using System.ServiceModel;
using System.ServiceModel.Activation;
using WinRT.Data;
using WinRT.DataAccess;

namespace WcfService
{
    [AspNetCompatibilityRequirements(
      RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    public class VSLiveService : IVSLiveService
    {
        public VSLiveService()
        {
            Database.SetInitializer(new Initializer());
        }

        public Session[] GetList()
        {
            using (var context = new Context())
            {
                context.Configuration.LazyLoadingEnabled = false;
                context.Configuration.ProxyCreationEnabled = false;
                return context.Sessions.ToArray();
            }
        }

        public Session Create(Session session)
        {
            using (var context = new Context())
            {
                context.Sessions.Add(session);
                context.SaveChanges();
            }
            return session;
        }

        public Session Update(Session session)
        {
            using (var context = new Context())
            {
                context.Entry(session).State = System.Data.EntityState.Modified;
                context.SaveChanges();
            }
            return session;
        }

        public void Delete(int sessionID)
        {
            using (var context = new Context())
            {
                var session = new Session { SessionID = sessionID };
                context.Entry(session).State = System.Data.EntityState.Deleted;
                context.SaveChanges();
            }
        }
    }
}

Now, the part that took me the longest to figure out: web.config.

I have single service node, and I have two endpoints for it, using the same contract, but two different bindings and behaviors.  I am putting entire web.config:

<?xml version="1.0"?>
<configuration>
  <connectionStrings>
    <add
          name="VSLive"
          connectionString="Server=.;Database=VSLive;Trusted_Connection=True;"
          providerName="System.Data.SqlClient"/>
  </connectionStrings>

  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <behaviors>
      <endpointBehaviors>
        <behavior name="jsonBehavior">
          <webHttp/>
        </behavior>
      </endpointBehaviors>

      <serviceBehaviors>
        <behavior>
          <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="true"/>
          <!—To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <basicHttpBinding>
        <binding
          name="VSLiveService_BasicHttpBinding"
          maxBufferSize="1000000"
          maxReceivedMessageSize="1000000">
          <readerQuotas
            maxBytesPerRead="1000000"
            maxArrayLength="1000000"
            maxDepth="1024"
            maxStringContentLength="1000000"/>
        </binding>
      </basicHttpBinding>
      <webHttpBinding>
        <binding
           name="VSLiveService_WebHttpBinding"
           maxBufferSize="1000000"
           maxReceivedMessageSize="1000000">
          <readerQuotas
            maxBytesPerRead="1000000"
            maxArrayLength="1000000"
            maxDepth="1024"
            maxStringContentLength="1000000"/>
        </binding>
      </webHttpBinding>

    </bindings>
    <services>
      <service name="WcfService.VSLiveService">
        <endpoint
          address="soap"
          binding="basicHttpBinding"
          bindingConfiguration="VSLiveService_BasicHttpBinding"
          contract="WcfService.IVSLiveService"/>
        <endpoint
            address="rest"
            binding="webHttpBinding"
            behaviorConfiguration="jsonBehavior"
            bindingConfiguration="VSLiveService_WebHttpBinding"
            contract="WcfService.IVSLiveService"/>
      </service>
    </services>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
  </system.webServer>
  <system.diagnostics>
    <sources>
      <source name="System.ServiceModel"
              switchValue="Information, ActivityTracing"
              propagateActivity="true">
        <listeners>
          <add name="traceListener"
              type="System.Diagnostics.XmlWriterTraceListener"
              initializeData= "c:\Traces.svclog" />
        </listeners>
      </source>
    </sources>
  </system.diagnostics>
</configuration>

As you can see above, SOAP endpoint comes first, and it is using basicHttpBinding.  My REST endpoint is second, and it is using webHttpBinding  I am asing a behavior configuration to the latter one, enabling webHttp get/post methods.

This is all nice and simple, and you can now test it in browser.  I an now add service reference to my WinRT project to support WCF.  You can find more details about that in my previous post http://dotnetspeak.com/index.php/2011/12/getting-started-with-wcf-services-in-winrt/

Today, I am documenting REST consumption.

I am using HttpClient class to accomplish this task.  For example, here is how I am going to get the list of sessions.

        public async Task LoadData()
        {
            IsBusy = true;
            _client = new HttpClient();
            _client.MaxResponseContentBufferSize = int.MaxValue;
            var response = await _client.SendAsync(new HttpRequestMessage(HttpMethod.Get, new Uri(_serviceUri + "GetList")));

            var data = response.Content.ReadAsString();

            DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(List<Session>));
            using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(data)))
            {
                var list = serializer.ReadObject(stream) as List<Session>;
                Sessions = new ExtendedObservableCollection<Session>(list);
            }
            IsBusy = false;
        }

A few points about the code above.  I should have wrapped the call inside Try/Catch, I am just skipping it for the sake of a demo and to minimize the code I am showing.  I am using standard serializer to convert my JSON message into an object.  I also have a little progress ring that is playing while server communication is going on, and that is what my IsBusy property above is bound to. 

Now, let’s take a look at Create/Update call.  It is just as simple, but I am using Post method of HttpClient and I am creating a string content to post by converting Session object to JSON, again using the same serializer.

        public async void OnSave(object parameter)
        {
            if (SelectedSession != null)
            {
                IsBusy = true;
                string method = "Update";
                if (selectedSession.SessionID == 0)
                {
                    method = "Create";
                }
                _client = new HttpClient();
                _client.MaxResponseContentBufferSize = int.MaxValue;
                var content = new StringContent(ConvertSessionToJson());
                content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
                var response = await _client.PostAsync(new Uri(_serviceUri + method), content);

                var data = response.Content.ReadAsString();

                var session = ConvertJsonToSession(data);
                Sessions[Sessions.IndexOf(selectedSession)] = session;
                SelectedSession = session;
                IsBusy = false;
            }
        }

For delete method I am also using Post method, just my content is blank and my ID is passed to the server as query string parameter

        public async void OnDelete(Session parameter)
        {
            if (parameter != null)
            {
                if (parameter.SessionID > 0)
                {
                    IsBusy = true;
                    _client = new HttpClient();
                    _client.MaxResponseContentBufferSize = int.MaxValue;
                    var content = new StringContent(string.Empty);
                    content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
                    var response = await _client.PostAsync(new Uri(_serviceUri + "Delete?sessionId=" + parameter.SessionID.ToString()), content);

                    var data = response.Content.ReadAsString();
                    Sessions.Remove(parameter);
                    IsBusy = false;
                }
                else
                {
                    Sessions.Remove(parameter);
                    IsBusy = false;
                }
            }
        }

Please let me know your questions.

Thanks.

Post to Twitter

JqGrid, getRowData and Cells in Edit Mode

Today I was fighting with a very specific problem.  I was working with jqGrid’s getRowData method.  I was implementing batch save feature, where a user can edit some data in the grid, then hit Save button to send the data to the server.  I set up a column (SortOrder) to be always editable to be more user friendly.  Here is what the column definition looks like for that column:


{ name: 'SortOrder', width: 100, index: 'SortOrder', align: 'left', search: false, 

editable: true, formattype: 'integer', formatoptions: { disabled: false }  },

Now, in my button click, I am calling getRowData, but instead of actual sort order value in the column, I get the html that defines the input field for SortOrder column.  There is no way around this, according to my research, so I had to manually parse the data out of the input field’s html.  Here is how I did that:

getGridData: function () {
  var gridData = $('#myGrid').jqGrid('getRowData');
  for (var i = 0; i < gridData.length; i++) {
    $('#myGrid').jqGrid('saveRow', gridData[i]['id'], false, 'clientArray');
  }
  gridData = $('#myGrid').jqGrid('getRowData');
  var pattern = /(id=\".+_SortOrder\")/ig;
  for (var j = 0; j < gridData.length; j++) {
     var sortOrder = gridData[j]['SortOrder'];
     if (sortOrder.toLowerCase().indexOf('<input') >= 0) {
         var matched = sortOrder.match(pattern)[0];
         var numberOfInput = matched.toUpperCase().replace("ID=\"", "").replace("_SORTORDER\"", "");
         sortOrder = $('#' + numberOfInput + '_SortOrder').val();
     }
     gridData[j] = {
       Name: gridData[j]['Name'],
       SortOrder: sortOrder
     };
  }
  return gridData;
}, 

Let’s walk through code.  First of all, I am calling saveRow for each row in the grid to save data to memory.  Then I am running through all the rows again, looking at my SortOrder column.  The other column, Name, is read-only.  I am using regular expressions to find HTML  Once this is found, I am parsing out input id.  The reason for that is because if you have more then one row in the grid, any row can have this input control, and it’s id corresponds to the row’s index in the grid.  Once this is done, I am getting the actual value by calling val() function.  Lastly, I am updating the value in the row.  Once this is done, I can use ajax function of jQuery to send the data to the server.  I use JSON.stringify(getGridData()) and then parse it back out on the server side in my controller’s method responsible for saving this data.

That’s all there is to it.

Thanks.

Post to Twitter

Implementing Error Handling in ASP.NET MVC

In this post I am going to try to document the solution to the following problem. I would like to implement custom global error handling in my ASP.NET MVC application using entity framework to log errors into the database.  Once the error is logged, I want to redirect the user to the custom page that will contain the newly generated error number so that they can contact support and give them more information about the error.

I am going to start with defining a custom error table in my DbContext.  In my case I am going to keep it simple, but you can add any custom columns you would like as long as you can get to the data from your executing application.

Here is how I am going to define my table and context

 

using System;

using System.ComponentModel.DataAnnotations;

 namespace MvcEFCodeFirst.Data

{

    public class AppError

    {

        public int AppErrorID { get; set; }

        public DateTime ErrorDateTime { get; set; }

        [StringLength(250)]

        public string UserIdentity { get; set; }

        public string ErrorText { get; set; }

    }

}

Of course, you can add any other columns you would like that suits your use case.  Then I add this table to my context via a new property:

public DbSet<AppError> AppErrors { get; set; }

Now, I am going to write the key part of the solution – my global error handler object.  It must do the following tasks:

  • Get the last error information
  • Log it into the table above
  • Redirect to the controller that will show a message to the user along with newly generated error (incident) number

The class is pretty simple, and works mostly on HttpContext.Current class to get the information it needs:

using System;

using System.Web;using System.Web.Mvc;

using System.Web.Routing;

using MvcEFCodeFirst.Controllers;

using MvcEFCodeFirst.Data;

using MvcEFCodeFirst.DataAccess;

namespace MvcEFCodeFirst.Helpers

{

    public static class ErrorHandler

    {

        public static void HandleError()

        {

            try

            

                // get the last error

                var exception = HttpContext.Current.Server.GetLastError();

                // clear out error information and any pending responses

                HttpContext.Current.Server.ClearError();

                HttpContext.Current.Response.Clear();

                // create new error to log

                var error = new AppError

                {

                    ErrorDateTime = DateTime.Now

                    ErrorText = exception.ToString(),

                    UserIdentity = HttpContext.Current.User.Identity.Name

                }

                // log error

                using (var context = new CodeStockContext())

                {

                    error = context.AppErrors.Add(error)

                    context.SaveChanges()

                }

                // redirect to error ErrorController.Index method

                // and pass in application error object so that the controller

                // could add error number to the page

                var routeData = new RouteData();

                routeData.Values.Add("controller", "Error");

                routeData.Values.Add("action", "Index");

                routeData.Values.Add("appError", error);

                ((IController)new ErrorController())

                    .Execute(new RequestContext(

                        new HttpContextWrapper(HttpContext.Current), routeData));

            }

            // ReSharper disable EmptyGeneralCatchClause

            catch (Exception)

            // ReSharper restore EmptyGeneralCatchClause

            

                //Ignore errors that occur during loggin

            

        }

    }

}

I added comments to demonstrate what I am doing in this class.

Now. let me show you my error controller, which is very simple and the Index view for it:

using System.Web.Mvc;

using MvcEFCodeFirst.Data;

namespace MvcEFCodeFirst.Controllers

{

    public class ErrorController : Controller

    {

        public ActionResult Index(AppError appError)

        {

            return View(appError);

        }

    }

}

Now, the view

@using MvcEFCodeFirst.Data

@model AppError

<h2>

    Error has occurred</h2>

<h4>

    An error has occurred and has been logged. Error number is @Model.AppErrorID.ToString().

    Please contact technical support.

</h4>

<br /

@Html.ActionLink("Main Menu", "", "")


And a few last steps.  I turn off custom errors in web config since I an implementing them differently now:

<system.web>

    <customErrors mode="Off"/>

</system.web>

And the last step is to call my error handler from Global.asax error handling routine:

using System;

using System.Web.Mvc;

using System.Web.Routing;

using System.Data.Entity;

using MvcEFCodeFirst.DataAccess;

using MvcEFCodeFirst.Helpers;

 
namespace MvcEFCodeFirst

{

    public class MvcApplication : System.Web.HttpApplication

    {

        public static void RegisterGlobalFilters(GlobalFilterCollection filters)

        {

            filters.Add(new HandleErrorAttribute());

        }

 
        public static void RegisterRoutes(RouteCollection routes)

        {

            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

 
            routes.MapRoute(

                "Default",

                "{controller}/{action}/{id}",

                new { controller = "Home", action = "Index", id = UrlParameter.Optional }

            );

 
        }

 
        protected void Application_Start()

        {

            AreaRegistration.RegisterAllAreas();

 
            RegisterGlobalFilters(GlobalFilters.Filters);

            RegisterRoutes(RouteTable.Routes);

 
            Database.SetInitializer(new DbInitializer());

        }

 
 

        protected void Application_Error(object sender, EventArgs e)

        {

            ErrorHandler.HandleError();

        }


    }

}

And that is all there is to it.  I know there is a bunch of other solutions, such as ELMAH, I saw while investigating my possible answers to the problem, but I think this one suits my goals the best.  Of course, you can also retrieve the error code from the exception by casting it to HttpException, but in my case I did not need to do that.  Another option is to use Response.Redirect instead of Controller.Execute, but this is a small variation of the same solution.

Thanks.

Post to Twitter

Entity Framework 4.3 Beta 1 Released

Entity framework team at Microsoft announced the beta release of the next version of Entity Framework Code First package, which now ships with migrations feature.

Read more about this release here
http://blogs.msdn.com/b/adonet/archive/2012/01/12/ef-4-3-beta-1-released.aspx

Thanks.

Post to Twitter

Deploying Database Project from TFS Build

Today I was working on a task that would allow us to deploy database project from team build.  We are using TFS 2008, by the way.  The reason I needed this functionality is because we wanted to run unit and integration tests as part of build as well as ensure that changes made to database project are valid.  With this goal established, we set to setup MSBuild project to do so.

First I scoured the internet for setup steps on MSDN.  There were a few articles, but nothing we tried worked.  I had to continue searching until finally found the correct combination of many steps to make it work.

I just opened the build project file in Visual Studio and edited it.  The file is called TFSBuild.proj and describes our continuous integration build in our case.  I also had to setup SQL Server to deploy database to and made sure that I have an account I can use to deploy the database.  Then I created connection string and added it to the PropertyGroup section just before </Project> tag of the project file.

  <PropertyGroup>
    <!– TEST ARGUMENTS
     If the RunTest property is set to true, then particular tests within a
     metadata file or test container may be specified here.  This is
     equivalent to the /test switch on mstest.exe.
 
     <TestNames>BVT;HighPriority</TestNames>
    
    –>
    <TargetConnString>Data&#x20;Source=ServerName%3BUser&#x20;ID=myUser%3BPassword=myPassword</TargetConnString>
  </PropertyGroup>

</Project>

If you look at the connection string, it does look strange.  The problem is that we have to encode it for MS Build not error out.  You could get a variety of errors, such as “Data Source is not a valid property, etc…”  So, you have to replace spaces in your connection string with &#x20; and semicolons with %3B.  Once this is done, the connection string is ready.  The next step is to setup a MS Build task.  It goes into Target section of AfterDropBuild type just before end of the file.

  <Target Name="AfterDropBuild">
    <Message Text="Starting to deploy database project"/>
    <MSBuild Projects="$(SolutionRoot)\MySolution\MyDatabase\MyDatabase.dbproj" 
Properties="TargetDatabase=DB_NAME;Configuration=Debug;OutDir=$(DropLocation)\$(BuildNumber)\Debug\;TargetConnectionString=$(TargetConnString);DeployToDatabase=true" 
Targets="Deploy"/>

    <Message Text="Finished deploying database project"/>
</Target>
 
</Project>

Let’s examine the task.  We are printing a couple of messages to make it easier to trace in the log file.  Then we have MSBuild task to deploy the database.  This Deploy target by default will also build the database project.  Then I am setting target database name – DB_NAME, then I am setting the location to script file that database project’s build process generates, then I set the connection string, pointing to the setting in the property group from the previous step, and lastly I set the crucial property – DeployToDatabase to true.

That is all.  Now my continuous integration  build will ensure that my database can successfully deploy and prepare the environment to run integration tests.

Thanks.

Post to Twitter

VS Live 2012 Las Vegas

I will be speaking at VS Live in Las Vegas in March 2012.

Visual Studio Live is five days of practical, Microsoft-supported training for developers to help solve your tough .NET development challenges. You’ll find how-to advice and the tips and tricks that you’ll be ready to implement as soon as you get back to the office. Our expert faculty – including many Microsoft instructors – makes each session interactive so you can discuss your particular development roadblocks and come away with actionable solutions.

Visual Studio Live Las Vegas offers in-depth training in:

  • Cloud Computing
  • Cross Platform Mobile
  • Data Management
  • HTML5
  • Silverlight / WPF
  • Visual Studio 2010+/.NET 4+
  • Web
  • Windows 8/WinRT
  • Windows Phone 7

Visual Studio Live Las Vegas – Expert Solutions for .NET Developers

You can keep up with a conference using one of the following

Twitter: http://twitter.com/vslive – #vslive
Facebook: http://www.facebook.com – Search “vslive”
LinkedIn: http://www.linkedin.com – - JOIN “vslive” GROUP

Attendees who register for Visual Studio Live Las Vegas using priority code VLSPK2 will receive all-access Best Value Conference Package for just $1,595, a savings of $500.00 off the standard price of $2,095

I will be presenting on two topics

Entity Framework Code First – Beyond the Basics

This session will cover scenarios beyond the basics. Topics such as creation of object hierarchies and complex types will be discussed. Performance tips will be covered as well as usage scenarios in services. Techniques to handle schema changes will be discussed. High level overview of how to handle various RDBMS with Entity Framework will be part of the conversation.

Building Data Driven Applications Using WinRT and XAML

This session will help attendees understand data access techniques in WinRT. The talk will highlight various ways to persists the data locally and via services. Topics will include data binding implications in regard with data usages, asynchronous access to data, and binding to various XAML controls.

Post to Twitter

Detecting Pending Changes in ASP.NET MVC

In this blog I am going to describe a pretty common problem that web applications have to deal with along with one way to solve this issue.

Here is the issue at hand.  Say, user pulled up an entry form and made some changes.  Then the above mentioned user clicked browser back button, navigating away from the current page, and thus loosing all the pending changes.  A friendly software application should warn the user, shouldn’t it?

So, how do we detect pending changes?  In typical desktop application, say the one that uses CSLA – http://lhotka.net/cslanet/, you can very easily check existing bound objects and see if there are pending changes.  CSLA, for example, takes a snapshot of business objects, then compare the snapshot to current state of the same object.  What if we could do the same?

To our benefit, there is a very useful function in jQuery, called serialize
http://api.jquery.com/serialize/

So, could we use that to solve the problem?  Let’s try something like

initialFormData = $(‘form’).serialize();

Seems pretty easy.  Now we need to create a JavaScript object that can help us to all the steps

  • Create snapshot of the data when it is loaded
  • Compare the snapshot to current data
  • Intercept navigation in progress and warn the user

I am going to create a brand new script file with my application in it, calling it App.js and define my object in it as following

if (!window.App) {
    window.App = {
        init:
function
() {
            window.onbeforeunload =
this
.onBeforeUnloadWindow;
           
this.initialFormData = $(‘form’
).serialize();
           
this.submitting = false
;
        },
        onBeforeUnloadWindow:
function
() {
           
return
window.App.hasPendingChanges();
        },
        submitting:
false
,
        initialFormData:
""
,
        hasPendingChanges:
function
() {
           
if (!window.App.submitting && 
                window.App.initialFormData !== $(
‘form’
).serialize()) {
               
return "You have pending changes. \n\rIf you leave current page, those changes will be lost."
;
            }
           
return
undefined;
        }
    };
}

Very quick and easy.  One small object, neatly organized that will do the work for me.  Now in my MVC application I locate _Layout.cshtml and include my script in the list of scripts.  The last step is to call init method on my App object after form loads, for example in Edit.cshtml:

<script type="text/javascript">
        window.App.init();
</script>

Now, if you try this solution, you will notice that your Save button does something strange.  It pops up the warning message for no reason.  So, we have to do one more thing in our Save button click event:

<input type="submit" onclick="window.App.submitting = true;" 
 
value=
@ViewBag.Action />

We have to let the App object know that we are navigating away because the user hit Save button.  That was our last step.  One of the guys on our team came up with this idea, and he and I refined it a bit to make the code cleaner.

Please let me know what you think.

Thanks.

Post to Twitter

jqGrid ajax Operations in ASP.NMET MVC

I am using jqGrid in my current project, and I already blogged prior on how impressed I am with the functionality available in this control.  I am using it in ASP.NET MVC application, but it can be used in any web app.  One of the key features is that it supports ajax based asynchronous server operations.

Upon my research I stumbled onto this article that greatly simplifies the code required to process search requests in ASP.NET MVS that are generated by the grid

http://www.codeproject.com/KB/aspnet/AspNetMVCandJqGrid.aspx

I had to make a small addition to it though.  The code works great in multi-search scenarios, but if you turn off multisearch option in search options, than you will get an error.  I also remove empty try/catch blocks which I personally find to be a bad practice.  Here is the updated code I used for Filter class:

using System.Runtime.Serialization;
using
System.Runtime.Serialization.Json;
using
System.Text;
 
[
DataContract
]
public class Filter

{
    [
DataMember]
   
public string groupOp { get; set
; }
    [
DataMember
]
   
public Rule[] rules { get; set
; }
 
   
public static Filter
Create(
       
string
jsonData, 
       
string
searchField, 
       
string
searchString, 
       
string
searchOper)
    {
       
Filter returnValue = null
;
       
if (!string
.IsNullOrEmpty(jsonData))
        {
           
var serializer = new DataContractJsonSerializer(typeof(Filter
));
           
using (var ms = new System.IO.MemoryStream(Encoding
.Default.GetBytes(jsonData)))
            {
                returnValue = serializer.ReadObject(ms)
as Filter
;
            }
 
        }
       
else

        {
            returnValue =
                   
new Filter()
                    {
                        groupOp =
"AND"
,
                        rules =
new[] { new Rule
() 
                        { data = searchString, field = searchField, op = searchOper } }
                    };
        }
       
return
returnValue;
    }
}

 

I added else statement that checks the json data variable, which will be null in cases of single field search.  The code will fall into same patch though, which is convenient because you process data code can stay the same whether or not you are using single or multi-search. 

Of course, I had to update the model binder to match:

using System.Web.Mvc;
 

public class GridModelBinder : IModelBinder

{
   
public object BindModel(
       
ControllerContext
controllerContext,
       
ModelBindingContext
bindingContext)
    {
       
var
request = controllerContext.HttpContext.Request;
       
return new GridSettings

        {
            IsSearch =
bool.Parse(request["_search"] ?? "false"),
            PageIndex =
int.Parse(request["page"] ?? "1"
),
            PageSize =
int.Parse(request["rows"] ?? "10"
),
            SortColumn = request[
"sidx"] ?? ""
,
            SortOrder = request[
"sord"] ?? "asc"
,
            Where =
Filter
.Create(
                request[
"filters"
],
                request[
"searchField"
],
                request[
"searchString"
],
                request[
"searchOper"
])
        };
    }
}

 

I want to thank Ilya Builuk for sharing his code.  I hope you will find my enhancements useful.  Another side thought.  There is a string based IQueryable extensions library that you can use to construct queries against this interface based on syntax such as “Where SomeColumn =- 2”.  Not that I am a giant fan of leaking my data access code into controllers or anything.  You can read more about dynamic linq on Scott Guthrie’s blog here

http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

Thanks.

Post to Twitter

Oracle ODP and Entity Framework Code First (4.2)

Oracle just released its newest version of Oracle Data Access Components (ODAC) that incudes support for Entity Framework 4.0.  You can read more about this release here http://www.oracle.com/technetwork/topics/dotnet/whatsnew/index.html.  You can also read this article about usage of ODP (Oracle Data Provider) with Entity Framework models http://www.oracle.com/technetwork/issue-archive/2011/11-sep/o51odt-453447.html

One important note is that Code First is not officially supported in this release, and will be supported in a future release.  Having said that, I wanted to see if I can use it, since Code First builds on top of EF 4, which is supported by this release.  I was able to confirm that I can indeed access Oracle data and update it. 

Here are step-by-step instructions.

You will need one prerequisite – Oracle engine itself.  I used 11g Express edition, which is free for developer.  You can download it from this page
http://www.oracle.com/technetwork/database/express-edition/downloads/index.html

Event those it is not required, I also installed Sql Developer, which is akin to SQL Server Management Studio, well mostly anyway.  You can download it from this page
http://www.oracle.com/technetwork/developer-tools/sql-developer/downloads/index.html

Once that is done, download and install ODAC from here
http://www.oracle.com/technetwork/topics/dotnet/whatsnew/index.html

At this point, I ran SQL Developer, connected to my instance and looked at the existing database.  You have to create a new connection for that, using File – New..->Database Connection menu. Under Other Users node I found HR, which contains a sample HR database.

image

Personally, I reset password for HR user to something that I know.  This way I do not have to use SYS login.

Now that those tasks are out of the way, you are ready to get started.  I assume you already have VS 2010 installed.

Now, start new project (I used Console application) and install Entity Framework Code First package reference into this project.  You can use NuGet for that, which is what I did.  Also add a reference to Oracle ODP assembly – Oracle.DataAccess.  Then, I create a POCO class to match Countries table and setup DbContext.  I use fluent API to configure that table.  I just do it in the context class instead of creating a separate configuring class.  Here is my country class.


   
public class Country
    {
       
public string CountryID { get; set; }
       
public string CountryName { get; set
; }
       
public decimal RegionID { get; set
; }
    }

 

And here is DbContext class:


   
public class Context : DbContext
    {
       
public Context()
            :
base(new OracleConnection(ConfigurationManager.ConnectionStrings["OracleHR"].ConnectionString), true
)
        {
 
        }
       
public DbSet<Country> Countries { get; set
; }
 
       
protected override void OnModelCreating(DbModelBuilder
modelBuilder)
        {
           
base
.OnModelCreating(modelBuilder);
            modelBuilder.Conventions.Remove<
IncludeMetadataConvention
>();
            modelBuilder.Entity<
Country>().Property(p => p.CountryID).HasColumnName("COUNTRY_ID"
);
            modelBuilder.Entity<
Country
>().HasKey(p => p.CountryID);
            modelBuilder.Entity<
Country>().Property(p => p.CountryName).HasColumnName("COUNTRY_NAME"
);
            modelBuilder.Entity<
Country>().Property(p => p.RegionID).HasColumnName("REGION_ID"
);
            modelBuilder.Entity<
Country>().ToTable("COUNTRIES", "HR"
);
        }
    }
 

 

Now, you have to setup connection string in app.config:

<?xml version="1.0"?>
<configuration>
               <connectionStrings>
                               <add name="OracleHR"
                                               connectionString="DATA SOURCE=localhost:1521/XE;PASSWORD=****;PERSIST SECURITY INFO=True;USER ID=HR;
"
                                               providerName="Oracle.DataAccess.Client" />

               </connectionStrings>
               <startup>
                               <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" />
               </startup>
</configuration>

 

Here is the code that gets data from the table and inserts a new row.

            using (var ctx = new Context())
            {
               
var
data = ctx.Countries.ToList();
                ctx.Countries.Add(
new Country() { CountryID = "CL", CountryName = "Chile"
, RegionID = 2 });
                ctx.SaveChanges();
            }

 

Here are a few important points.

  • Make sure to put correct password into connection string.
  • I configure column names explicitly to match the database table. 
  • I had to use correct .NET types to match the Oracle data types.  Here is MSDN article that describes this mapping http://msdn.microsoft.com/en-us/library/yk72thhd.aspx
  • I am manually creating Oracle Connection and passing it into constructor of my context class.  I tried to avoid that, but I kept getting exceptions.  This approach worked perfectly.

In summary, one apparently can use newest Oracle provider to use with Code First.  This approach is not officially supported by Oracle, at least not yet.  So, use it at your own risk.  You definitely cannot create new database as you can in SQL Server, so you have to maintain database separately.  From my research, only DevArt provides full Code First support for Oracle with their own provider, at least according to their product page http://www.devart.com/dotconnect/entityframework.html

You can download my sample solution http://DotNetSpeak.com/Downloads/EFOracle.zip

[Update 2/12/2012] – this scenario is not officially supported by Oracle, so you should not use this in production.

Thanks, and feedback is appreciated.

Post to Twitter

Securing WCF with Forms Authentication

In this post I will describe how to secure a WCF RESTful service with Forms Authentication.  I blogged on WCF many a times, but usually skipped right over security aspects of the service.  I will go into sufficient (hopefully) level of details now.

The idea of having an un-secured service on the internet is not an appealing one.  This means that anyone can connect to it and consume the data exposed by the service.  Yes, granted, that person would have to discover your service somehow, but still the aspects of security cannot be ignored.  As a result, we must authenticate and authorize every consumer of the service.  For authentication I will use forms authentication.  One of primary reasons why I want to do that is because I do not have to litter my API with user Id and password for every method.  Instead I will rely on built-in functionality in ASP.NET to do a bulk of heavy lifting for me.  Once ASP.NET established the user, I will generate an authorization cookie, and that cookie will be consumed by the client, and then re-submitted with requests.

So, here is my solution at a high level.

  • Create authentication WCF Service
  • Create Data WCF RESTful service, which has actual API I am exposing.
  • Secure the site with forms authentication.
  • Client will first call authentication service, get a cookie, then submit it with requests to RESTful service.

Let’s start by creating a RESTful service.  Just use built-in template in Visual Studio 2010

image

Now because I want a real service, I am going to use Entity Framework Code First to create some basic functionality to perform CRUD operations on a Person object.

 

namespace CustomWcfRestService
{
    public class Person
    {
        public int ID { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set;}
    }
}

I am also going to have a users table I am going to use for authentication.

namespace CustomWcfRestService
{
    public class User
    {
        public int UserID { get; set; }
        public string UserName { get; set; }
        public string Password { get; set; }
    }
}

Here is sample code for my operational RESTful service.  I am using json format for everything.

using System.Collections.Generic;
using
System.Data;
using
System.Linq;
using
System.ServiceModel;
using
System.ServiceModel.Activation;
using
System.ServiceModel.Web;
using
System.Web.Script.Services;
 

namespace
CustomWcfRestService
{
    [
ServiceContract
]
    [
AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode
.Required)]
    [
ServiceBehavior(InstanceContextMode = InstanceContextMode
.PerCall)]
   
public class CustomService

    {
        [
WebGet(UriTemplate = "/GetPeople", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
       
public List<Person
> GetPeople()
        {
           
using(var ctx = new Context
())
            {
                ctx.Configuration.LazyLoadingEnabled =
false
;
                ctx.Configuration.ProxyCreationEnabled =
false
;
               
return
ctx.People.OrderBy(one => one.LastName).ThenBy(two => two.FirstName).ToList();
            }
        }
 
        [
WebInvoke(UriTemplate = "/Create", Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat
.Json)]
       
public Person Create(Person
person)
        {
           
using (var ctx = new Context
())
            {
                ctx.Entry(person).State =
EntityState
.Added;
                ctx.SaveChanges();
               
return
person;
            }
        }
 
        [
WebGet(UriTemplate = "/GetPerson?id={id}", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat
.Json)]
       
public Person Get(int
id)
        {
           
using (var ctx = new Context
())
            {
                ctx.Configuration.LazyLoadingEnabled =
false
;
                ctx.Configuration.ProxyCreationEnabled =
false
;
               
return
ctx.People.Find(id);
            }
        }
 
        [
WebInvoke(UriTemplate = "/UpdatePerson", Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat
.Json)]
       
public Person Update(Person
person)
        {
           
using (var ctx = new Context
())
            {
                ctx.Entry(person).State =
EntityState
.Modified;
                ctx.SaveChanges();
               
return
person;
            }
        }
 
        [
WebInvoke(UriTemplate = "/GetPerson?id={id}", Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat
.Json)]
       
public void Delete(int
id)
        {
           
using (var ctx = new Context
())
            {
               
var person = new Person
{ID = id};
                ctx.Entry(person).State =
EntityState
.Deleted;
                ctx.SaveChanges();
            }
        }
 
    }
}

 

I am now going to add a new service, called LoginService that I will use for authentication.  It will use the same Users table to validate user name and password.

using System;
using
System.Linq;
using
System.ServiceModel;
using
System.ServiceModel.Activation;
using
System.Web.Security;
using
System.Web;
 

namespace
CustomWcfRestService
{
    [
AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode
.Required)]
    [
ServiceBehavior(InstanceContextMode = InstanceContextMode
.PerCall)]
   
public class LoginService : ILoginService

    {
 
       
public bool Login(string userName, string password)
        {
           
bool returnValue = false
;
           
User
user;
           
using (var ctx = new Context
())
            {
                user = ctx.Users.Where(one => one.UserName == userName).FirstOrDefault();
               
if (user != null
)
                {
                    returnValue = (user.Password == password);
                }
            }
           
if
(returnValue)
            {
               
var ticket = new FormsAuthenticationTicket
(
                        1,
                        userName,
                       
DateTime
.Now,
                       
DateTime
.Now.AddDays(1),
                       
true
,
                        user.UserID.ToString()
                    );
               
string encryptedTicket = FormsAuthentication
.Encrypt(ticket);
               
var cookie = new HttpCookie(FormsAuthentication
.FormsCookieName, encryptedTicket);
               
HttpContext
.Current.Response.Cookies.Add(cookie);
 
            }
           
return
returnValue;
        }
    }
}

 

As you can see, I validate credentials against database, then I am creating custom cookie, encrypting it and sending back to the client.  I have to use ASP.NET compatibility mode to enable HttpContext and related functionality.

Now, I need to enable actual security.  I am doing this entirely in Web.Config by enabling forms authentication, denying requests from un-authenticated users, then adding a Location exception just for my login service.

<?xml version="1.0"?>
<configuration>
    <connectionStrings>
        <add name="SecuredServiceDemo"
           connectionString="Server=.;Integrated Security=SSPI;Database=SecuredServiceDemo
"
           providerName="System.Data.SqlClient" />

    </connectionStrings>
    <system.web>
        <compilation debug="true" targetFramework="4.0" />
        <authentication mode="Forms">
        </authentication>
        <authorization>
            <deny users="?"/>
        </authorization>
    </system.web>
 
    <location path="LoginService.svc">
        <system.web>
            <authorization>
                <allow users="?"/>
            </authorization>
        </system.web>
    </location>

 

 

And that is it.  Now just create a test client as in following:

using System.Net;
using
System.ServiceModel;
using
System.ServiceModel.Channels;
using
TestServiceApp.LoginService;
using
System.IO;
 

namespace
TestServiceApp
{
   
class Program

    {
       
static void Main(string[] args)
        {
           
var sharedCookie = string
.Empty;
           
bool
isValid;
           
string data = string
.Empty;
 
           
var authClient = new LoginServiceClient
();
           
using (new OperationContextScope
(authClient.InnerChannel))
            {
                isValid = authClient.Login(
"me@you.com", "pw"
);
               
if
(isValid)
                {
                   
var response = (HttpResponseMessageProperty)OperationContext.Current.IncomingMessageProperties[HttpResponseMessageProperty
.Name];
                    sharedCookie = response.Headers[
"Set-Cookie"
];
                }
            }
 
           
if
(isValid)
            {
 
               
var request = (HttpWebRequest)WebRequest.Create("http://localhost:48090/CustomService/GetPeople"
);
                request.Headers[
"Cookie"
] = sharedCookie;
               
var
responce = request.GetResponse();
               
using (var
stream = responce.GetResponseStream())
                {
                   
using (var reader = new StreamReader
(stream))
                    {
                        data = reader.ReadToEnd();
                    }
                }
            }
 
        }
    }
}

 

Just to confirm that everything is working, I can just comment out the part that authenticates and gets a cookie, and I get 404 as expected.

You can download the complete solution here and try yourself.

Post to Twitter

Reflections on Past Year

I got a notification today that my Microsoft MVP status has been extended for one more year.  This is a great news for me, and makes me feel even more proud of the work I do in the community.  I have always loved participating in the local Microsoft focused user groups and gatherings.  I enjoy hanging around my peers and learning from them, exchanging honest opinions, and presenting on occasion.  I believe that sharing knowledge is vital for any developer to stay current with technology, and I think this equally applies to attending events, presenting and volunteering alike.  Atlanta has a vibrant Microsoft focused developer communing, and there is always something going to match any programming interest.

I think working for Magenic Technologies has been instrumental in keeping me involved and learning.  Magenic as a company highly encourages its employees to be learners and teachers, awarding and encouraging everyone who participates in community events.

I see blogging as an activity that serves multiple purposes as well.  I blog mostly about topics that interest me, and as part of writing I also learn various aspects of Microsoft developed technologies.  The fact that some people find my writings useful just motivates me even more.  Here are the visitor stats on my blog since I moved it here after purchasing DotNetSpeak.com.

image

Thanks and Happy New Year.

Post to Twitter

Getting Started with WCF Services in WinRT

I have been learning WInRT in my “spare time” since for a while now. My big interest is working with data in Metro style applications for Windows 8. In this post I will describe step-by-step instructions of creating a WinRT application that is using WCF Service. I am going to use XAML application. To get started, just create a brand new XAML based application in Visual Studio 11. Then I am going to create a WCF Service that is using Entity Framework code first.

I created just on table/class, data context and a WCF host web application.

public class Session

{

    public int SessionID { get; set; }

    public string Title { get; set; }

    public string Description { get; set; }

    public string Speaker { get; set; }

    public DateTime When { get; set; }

}

using System.Data.Entity;

using WinRT.Data;

namespace WinRT.DataAccess

{

    public class Context : DbContext

    {

         public Context() :

           base("Name=VSLive")

         {

         }

         public DbSet<Session> Sessions { get; set; }

         protected override void OnModelCreating(DbModelBuilder modelBuilder)

         {

             base.OnModelCreating(modelBuilder);

             modelBuilder.Entity<Session>().

                     Property(p => p.Title).HasMaxLength(100).IsRequired();

             modelBuilder.Entity<Session>().

                     Property(p => p.Speaker).HasMaxLength(50).IsRequired();

             modelBuilder.Entity<Session>().

                     Property(p => p.Description).IsRequired();

             modelBuilder.Entity<Session>().

                     Property(p => p.When).IsRequired();

           }

      }

}

Service class is not very complicated either, here is get method:

public Session[] GetList()

{

      using (var context = new Context())

      {

           context.Configuration.LazyLoadingEnabled = false;

           context.Configuration.ProxyCreationEnabled = false;

           return context.Sessions.ToArray();

       }

}

Now, I am going to configure service to use IIS and setup AppPool to have enough rights to create a database.

Now in my XAML Metro application I right click on references and choose Add Service Reference. I will clock on button in the next dialog to discover services in the solution and click OK to add a reference. This will create a proxy class to communicate with my service. One interesting thing about this class in comparison with the same proxy in .NET or Silverlight is that it is using new async / await keywords and Tasks to simplify the code on the client.

Now, I am going to add a view model class that will have all the communication with the service. First of all, it has to create proxy instance with proper configuration.

private VSLiveServiceClient _client;

private void SetupClient()

{

      BasicHttpBinding binding =
           new BasicHttpBinding(BasicHttpSecurityMode.None);

      binding.AllowCookies = true;

      binding.MaxBufferSize = int.MaxValue;

      binding.MaxReceivedMessageSize = int.MaxValue;

      binding.OpenTimeout = TimeSpan.FromSeconds(10);

      EndpointAddress address = new EndpointAddress(_serviceUri);

      _client = new VSLiveServiceClient(binding, address);

}

Now I can invoke the service by calling the proxy:

public async Task LoadData()

{

      var sessions = await _client.GetListAsync();

      Sessions = new ExtendedObservableCollection<Session>(sessions);

}

You can read a bit more about my ExtendedObservableCollection in one of my previous posts at http://dotnetspeak.com/index.php/2011/11/observablecollectiont-in-winrt/. Now I am ready run. But what I am getting is “There was no endpoint listening at ….” The issue is that I have to add an exemption to allow WinRT application to communicate with a service at localhost. The tool is called CheckNetIsolation. You can get to it by running Visual Studio Command prompt. But you have to find the application ID for that. To do so you have to run RegEdit and find your application. Here is path you are looking for:

HKEY_CURRENT_USER\Software\Classes\Local Settings\Software\Microsoft\Windows\CurrentVersion\AppContainer\Mappings

Once you find the path, just go through all nodes and look for you application by looking at DisplayName entry node. Once you find it, click on a node name(starts with S-1-…), select Rename and hit Ctrl+C to copy node name to the clipboard.

image

Mine was S-1-15-2-4269264600-3040727888-3229327272-2989798893-2153435301-719469956-2341848450.

Now in VS Command prompt type :

CheckNetIsolation LoopbackExempt -a -p=S-1-15-2-4269264600-3

040727888-3229327272-2989798893-2153435301-719469956-2341848450

and hit enter. Make sure you spell everything correctly, the command line is case-sensitive.

Now, run your application. You should be ready to go. If you still get an error, edit the manifest file (double-click on Package.appxmanifest file in your WinRT project, go to capabilities tab and check home networking and Internet Client.

image

You will also need to turn off (or configure) Windows Firewall.

You are now ready to go.

Thanks.

Post to Twitter

Creating Enumerations from Database With T4

I personally have not spent a lot of time studying T4, but I am aware of tremendous power of the tool.  I ran across a good use case, and I am totally convinced that I will not do another project now without using this code generation tool.

To gets started, I picked up an editor to install.  I just used Extensions Manager from Tools menu of Visual Studio to search for T4 editor, and picked Visual T4.  It provides very impressive development environment, including color coding and IntelliSense.  T4 files are just code files that mix code and text.  When the tool is run, it runs the code in the file, and processes the text in it at the same time.

My task is to create an enumeration in C# that is mirroring data in a table.  My table looks as following:

USE [SampleEnum]
GO

CREATE TABLE [dbo].[EnumTable](
    [ID] [int] NOT NULL,
    [Name] [nvarchar](50) NOT NULL,
    [Description] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_EnumTable] PRIMARY KEY CLUSTERED ([ID] ASC)
)

GO

 

Now, I just choose New Item menu, and select Text File option in my project.  I then name the file with the same name as my class and .tt extension.  Once I open in in Visual Studio, I get IntelliSense support.  On top of the file I have assembly references and using statements, similar to any other plain ol’ C# class.  Syntax is different though, and looks as following.

<#@ Template Language="C#" Hostspecific="True" Debug="True" #>

<#@ Assembly Name="EnvDTE" #>

<#@ Assembly Name="System.Data" #>

<#@ import namespace="System.Data" #>

<#@ Import Namespace="System.Data.SqlClient" #>

<#@ Import Namespace="System.Data.Common" #>

Then, I have a combination of plain text and C# code:

<#@ Template Language="C#" Hostspecific="True" Debug="True" #>

<#@ Assembly Name="EnvDTE" #>

<#@ Assembly Name="System.Data" #>

<#@ import namespace="System.Data" #>

<#@ Import Namespace="System.Data.SqlClient" #>

<#@ Import Namespace="System.Data.Common" #>

/// <summary>

/// User types

/// </summary>public enum UserTypes{ <#    SqlConnection connection = new SqlConnection("Data Source=(local);Initial Catalog=SampleEnum;Trusted_Connection=true");

    connection.Open();

    SqlCommand commandTotal = connection.CreateCommand();

    commandTotal.CommandType = CommandType.Text;

    commandTotal.CommandText = "SELECT Count(1) FROM [EnumTable]";

    var total = (int)commandTotal.ExecuteScalar();

    SqlCommand command = connection.CreateCommand();

    command.CommandType = CommandType.Text;

    command.CommandText = "SELECT [ID],[Name],[Description] FROM [EnumTable] ORDER BY NAME ";

    var reader = command.ExecuteReader();

    int counter = 1;

    while (reader.Read())

    { 

#>

	/// <summary>

	/// <#= reader[2] #>

	/// </summary>

	<#= reader[1] #> = <#= reader[0].ToString() #><# if (counter < total) #>,

	<# counter++;#>

 
<#    }

    reader.Dispose();

    connection.Close();

    connection.Dispose();

#>


}

The code is pretty self-explanatory.  I just use data reader and command classes to get the data

from my table, then write code as regular enumeration – comment, then enumeration name, then value.  Easy.  Then I just add data to my table, then right-click on tt file and select Run Custom Tool menu.

This is just a small taste of extreme power of T4.  If you never used the tool, take a look, you will not be disappointed.

Thanks

Post to Twitter

Localizing JavaScript in ASP.NET MVC

This is something I researched recently while working on an ASP.NET MVC application.  My goal was to localize JavaScript messages based on user preferences.  In this post I am going to document the approach I settled on.  I am going to test based on browser culture and also drive the application based on the same preferences.

First of all, here is how I am setting up for testing using Internet Explorer.  Go to Settings menu, then select Internet Options.  You will see Languages button.

 

image

Once I am there, I am going to add Spanish for testing.

image

I can now test by moving preferred language up and down.

Now, in my controller (you can do in the base controller or any other place that can e hit before any code that manipulates the user interface, such as labels or JavScript.  Here is an example from Home controller in a brand new MVC app.  If you add a brand new MVC project, you will see that controller.  You can always create a base class and put your code there, which is what I did.

using System.Globalization;
using System.Threading;
using System.Web.Mvc;

namespace LocalizeJavaScriptMvc.Controllers
{
    public class HomeController : Controller
    {
        private void SetCulture()
        {
            if (HttpContext.Request.UserLanguages != null &&
                HttpContext.Request.UserLanguages.Length > 0)
            {
                Thread.CurrentThread.CurrentCulture =
                    new CultureInfo(HttpContext.Request.UserLanguages[0]);
                Thread.CurrentThread.CurrentUICulture =
                    Thread.CurrentThread.CurrentCulture;
            }
        }
        public ActionResult Index()
        {
            ViewBag.Message = MainResource.Title;

            return View();
        }

        public ActionResult About()
        {
            return View();
        }

        protected override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            SetCulture();
        }
    }
}

So, now my main thread has been setup.  Next, I am going to create two resource files. One with code generation, specifically MainResource.resx.  Just Select Add New Item from project menu, and select new Resource, then give it the name as above.  Repeat the step, this type using MainResource.es.resx.  Pull up MainResource in the editor window, add some strings and set it’s access modifier to public:

image

 

Now, to JavScript.  My experience in the language is somewhat limited, but I dutifully read the most recommended book on the language, JavaScript – the Good Parts many months back.  So, I added brand new JavaScript file to my project with my class that will be responsible for localization – mainApp.js. 

if (!window.resourceProvider) {
    window.resourceProvider = {
        message1: ”,
        message2: ”
    };
}

My resourceProvider class has two properties, that I set to empty strings. I like defining properties because I get IntelliSense when I do. In my “master page” – layout page – _Layout.cshtml I need to include my new script

<head>
<meta charset="utf-8" />
<title>@ViewBag.Title</title>
<link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/modernizr-1.7.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/mainApp.js")" type="text/javascript"></script>
</head>

The last step is to populate my message1 property with the actual text. I will do that in the bottom of the view:

    </div>
</body>
</html>
<script type="text/javascript">
    resourceProvider.message1 = ‘@(MainResource.Message1)’;
</script>
Now, I just need to call it from JavaScript. For testing, I am just adding a button ti Index.cshtml and script to invoke Click event with a simple alert:
@using LocalizeJavaScriptMvc
@{
    ViewBag.Title = "Home Page";
}
<h2>@ViewBag.Message</h2>
<p>
    <button id="clickhere">@MainResource.Click</button>
</p>
<script type="text/javascript">
    $().ready(function () {
        $(‘#clickhere’).click(function () {
            alert(resourceProvider.message1);
        });
    })
</script>

As you can see, I am localizing button text and using my resourceProvider class with its message1 property to localize the alert.

To test, I just set preferred language in browser to English and Spanish, and run the app twice to test.

You can download solution at http://dotnetspeak.com/Downloads/LocalizeJavaScriptMvc.zip

Please let me know if you have any comments regarding this solution.

Thanks.

Post to Twitter

Support for Roaming Folder in WInRT Database

I posted another small update to my WinRT database project on CodePlex.

I added support for roaming.  You can now specify the location of the database, picking either local or roaming folder.  For example, here is how you can create database in Roaming folder:

_database = await
   Database.CreateDatabaseAsync(DatabaseName, StorageLocation.Roaming);

I added the same parameter – StorageLocation to OpenDatabaseAsync and DoesDatabaseExistsAsync method for full support.  If you are curious on how this was done, I used support for those folder that can be found via properties on ApplicationData.Current class/property.

Please let me know of any suggestions you might have.  Feedback is always appreciated.

I update quick start project, included in the download, to demonstrate the use of new functionality.

Thanks.

Post to Twitter

Addition of IsDirty flag to WinRT Database Project

If you follow my posts, you noticed that I started up WinRT database project on CodePlex. I just published as small update to it that now support data binding of commands objects to IsDirty flag on database and each table.  The code is quite simple, for example here is how Save command is setup. 

public SimpleCommand<object> SaveCommand { get; set; }


public void OnSave(object
parameter)
{
  if (_database != null
)
  { 
    _database.SaveAsync();
  }
}

public bool CanSave(object parameter)
{
  return (_database != null
&& !_database.IsBusy && _database.IsDirty);
}

Now you can have cleaner UI, where Save button provides visual feedback to the users. Comments are welcomed as always.

Thanks.

Post to Twitter

VS Live Orlando 2011

As I mentioned before, I presented at VS Live conference in Orlando, FL Thursday, 12/08/2011. I presented the following two talks

Working with Data on Windows Phone 7
I will talk about various approaches to work with data on Windows Phone 7. I will cover all major concepts, such as local storage, OData/WCF Data Services and custom WCF services. I will demonstrate how to retrieve data and save changes locally or to a remove web server. I will build demos for all technologies step-by-step.

You will learn:
• About options to persist the data on Windows Phone 7
• About pros and cons of each technologies
• Knowledge to build a Windows Phone application that publishes and/or consumes data

You can download the materials for this presentation here.

Using Code First (Code Only) Approach with Entity Framework
Session will include high level overview of Entity Framework and how various approaches to use it fit into application development lifecycle. Then I will build POCO classes that entity framework can use to create database as well as perform CRUD operations against the database. Various attributes that are included out of the box will be covered. This will include columns constraints, relationships, etc. I will show you how ASP.ENT MVC 3 can utilize entity framework code first metadata to build automatic validation of user input.
You will learn:
• How to build data access layer with Entity Framework Code First
• About validation approaches using POCO classes
• Fluent API and attribute based configuration option

You can download the materials for this presentation here.  I spent a lot of time answering questions, which I really enjoy, so I ran a bit short on time covering MVC.  On a positive note, you can still see the project in the download zip file.

Feel free to ask any questions related to the presentations in the comments or email me directly.  You can find my email address on Contact Me page on this blog.

Post to Twitter

INotifyPropertyChanged, WinRT and Shortcuts

INotifyPropertyChanged interface is the key to data binding in many UI Microsoft frameworks, such as Windows Forms, WPF and Silverlight.  All controls in all those frameworks listen to this interface in the classes these controls are bound to and refresh the UI based on those changes.  This interface lives in System.ComponentModel, and you can read more about it here.

In WinRT, Windows 8 runtime this interface moved to a different namespace – Windows.UI.Xaml.Data.  You can see details of here.

As this interface is important, and I want to rely on it in new features I am going to add to my WinRT database project, I wanted to make it easier for people to create classes that implement it and easily add properties to those classes.  So, I wanted to publish this knowledge as well as walk through some of the Visual Studio features that allow  developers create item templates and snippets.  I am planning to use both in this quick post.

Let’s start by creating a class template.  We start by creating a class and make it look like we want it to.  It is really easy, and here is the entire code.

using System;
using Windows.UI.Xaml.Data;

namespace Application1
{
    public class NotifyPropertyChangedClass : INotifyPropertyChanged
    {

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

 

Now, we need to create a class template.  This step is just as easy.  Select Export Template from File menu in Visual Studio:

image

 

Click Next

image

We are selecting our class here, then clicking next.

image

We will skip the references (uncheck all), then click Next.

image

On this last screen I am going to give my new template name and description, I can optionally add icon and preview image, select to automatically import the template, then click Finish.

No, to test this template, I am just right-click on property, select Add New item, then search for notify property changed.

image

Just change the class name and click Add.  Voila – new class that looks just like my template has been added.

Now the snippets.  I am going to use “propfull” snippet as a base.  This snippet adds a property with backing field.  First, I need to see where those snippets are installed.  I can see that by going to Tools –> Code Snippets Manager, then selecting your language, C# in my case.

image

I just expand Visual C# tree node, then I can see the Location.  I am going to that location, find file calld propfull,snippet, then copy it to any folder.  I then rename it propnpc.snippet, where ncp stands for Notify Property Changed.  You can use any name you like.  Then I edit this file in Visual Studio. 

image

I edit Title, description and shortcut, as well as author.  The last part is edit the actual snippet code (in light grey at the bottom of the screenshot).  I simply add the call to OnPropertyChanged method I established when I created a class template before.  Here is the code:

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
    <CodeSnippet Format="1.0.0">
        <Header>
            <Title>propnpc</Title>
            <Shortcut>propnpc</Shortcut>
            <Description>Code snippet for property and backing field that calls property changed</Description>
            <Author>Sergey Barskiy</Author>
            <SnippetTypes>
                <SnippetType>Expansion</SnippetType>
            </SnippetTypes>
        </Header>
        <Snippet>
            <Declarations>
                <Literal>
                    <ID>type</ID>
                    <ToolTip>Property type</ToolTip>
                    <Default>int</Default>
                </Literal>
                <Literal>
                    <ID>property</ID>
                    <ToolTip>Property name</ToolTip>
                    <Default>MyProperty</Default>
                </Literal>
                <Literal>
                    <ID>field</ID>
                    <ToolTip>The variable backing this property</ToolTip>
                    <Default>myVar</Default>
                </Literal>
            </Declarations>
            <Code Language="csharp"><![CDATA[private $type$ $field$;

    public $type$ $property$
    {
        get { return $field$;}
        set { $field$ = value; OnPropertyChanged("$property$"); }
    }
    $end$]]>
            </Code>
        </Snippet>
    </CodeSnippet>
</CodeSnippets>

The last step is to copy the new snippet back to the original folder.  I could also establish new folder for custom template, but I do not feel like dealing with that.  Now, just type propnpc and hit Tab in your newly added class, and you end up with the following:

image

Just keep changing data, and hitting Tab to advance to the next expansion area, and you will end up with:

image

You are done.  You can also take this a step further, and create a base abstract class that implement INotifyPropertyChanged, then have all your classes inherit for it.

Enjoy.

Thanks.

Post to Twitter

Update to WinRT File Based Database

I just posted new version for my CodePlex based project for WinRT database.  This chance is small – I added IsBusy property to the database class in order to enable data binding scenarios between buttons and commands.  You can take a look at the Quick Start project that distributed as part of the download for sample use of this property to support Save button on the main screen.

Please let me know if you have any questions.

Thanks.

Post to Twitter

Update to EF Extras Project

As I blogged about this before, I continue working on my Entity Framework Code First extras project on CodePlex.  Today I added support for indexes to the functionality of the project.  I bumped up the version to 0.9.4.  I wanted an ability to declaratively express indexes on tables via attributes.  So, I added a new attribute to support that:

using System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
 

namespace
EFUtil.Core.Indexes
{
          
/// <summary>

          
/// Used to specify an index for a column
          
/// </summary>
           [
AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
          
public class IndexedAttribute : Attribute

           {
                     
/// <summary>
                     
/// Create new instance of the indexed attribute
                     
/// </summary>
                     
/// <param name="indexName">Name of the index</param>
                     
/// <param name="ordinalPosition">Position of the column in an index</param>
                     
/// <param name="columnName">Column name for the index</param>
                     
/// <param name="direction">Direction of the column sorting in an index</param>
                     
/// <param name="tableName">Table name for the index</param>
                     
public IndexedAttribute(
                                
string
indexName,
                                
int
ordinalPosition = 0,
                                
string columnName = ""
,
                                
IndexDirection direction = IndexDirection
.Ascending,
                                
string tableName = ""
)
                      {
                                 IndexName = indexName;
                                 OrdinalPoistion = ordinalPosition;
                                 TableName = tableName;
                                 ColumnName = columnName;
                                 Direction = direction;
                      }
 
                     
/// <summary>

                     
/// Position of the column in an index
                     
/// </summary>
                     
public int OrdinalPoistion { get; private set; }
 
                     
/// <summary>

                     
/// Direction of the column sorting in an index
                     
/// </summary>
                     
public IndexDirection Direction { get; private set; }
                     
/// <summary>

                     
/// Table name for the index
                     
/// </summary>
                     
public string TableName { get; private set; }
 
                     
/// <summary>

                     
/// Column name for the index
                     
/// </summary>
                     
public string ColumnName { get; private set; }
 
                     
/// <summary>

                     
/// Name of the index
                     
/// </summary>
                     
public string IndexName { get; private set
; }
           }
}

 

This attribute allows you specify all index properties, such as name, direction (ascending or descending) and a column’s ordinal position in the index.  Here is sample usage in a table (class):

using System;
using
EFUtil.Core.Defaults;
using
EFUtil.Core.Indexes;
 

namespace
EFUtil.TestApplication
{
          
public class Product

           {
                     
public int ProductId { get; set; }
                      [
Indexed("Main"
, 0)]
                     
public string ProductNumber { get; set
; }
                      [
Indexed("Main"
, 1)]
                      [
Indexed("Second", direction: IndexDirection
.Ascending)]
                      [
Indexed("Third", direction: IndexDirection
.Ascending)]
                     
public string ProductName { get; set
; }
                     
public string Instructions { get; set
; }
                      [
Indexed("Third", 1, direction: IndexDirection
.Descending)]
                     
public bool IsActive { get; set
; }
                      [
Default("0"
)]
                     
public decimal? Price { get; set
; }
                      [
Default("GetDate()"
)]
                     
public DateTime? DateAdded { get; set
; }
                      [
Default("20"
)]
                     
public int Count { get; set
; }

           }
}
 

 

As you can see above, I declare a number of indexes, where index called Third has two columns – ProductName and IsActive in that exact order and different directions.  This combination will translate in the following:

CREATE NONCLUSTERED INDEX [Third] ON [dbo].[Products]

(

      [ProductName] ASC,

      [IsActive] DESC

)

 

 

 

I am trying with this implementation to get even further in eliminating a need to use scripting or separate database project to maintain the information about the database when using Code First.

Please let me know if you have any questions.

Thanks.

Post to Twitter

Encrypting and Decrypting Data in WinRT

As part of working on WinRT database I wanted to support ability to encrypt the data. The reason for that is that the data you persist using file system can be opened essentially in NotePad as long as you know where it is stored on the hard drive, which you can figure out. So, similarly to how I support encryption in Silverlight, I wanted to do the same in WinRT. I did some digging, and did find bits and pieces of information on the Win RT forum and in samples. Nothing however fully explained and had examples for encrypting and decrypting strings, which is what I wanted to accomplish. As a result, I wrote a helper class that I wanted to share.

My requirement were simple: just have two methods in a static class that take two parameters: input string and a password to use. I do not exactly use the password, but I use it to create a key: If you try to hack the code and pass password that was not used to encrypt into decryption method, you will get an exception. One thing that I found extremely annoying, is that all exceptions are coming in as COM exception (oh, no, do not take me back into the 90s – smile)

I added commented everywhere to make clear what I am doing. I coded this class using AES encryption provider. There is an ability in SymmetricKeyAlgorithmProvider.OpenAlgorithm to use various algorithms, but I could not find the list to save my life. As a result, I used the one mentioned in an example on the web – AES_CBC_PKCS7.

using System;
using System.Text;
using Windows.Security.Cryptography;
using Windows.Security.Cryptography.Core;
using Windows.Storage.Streams;
namespace EncryptDecrypt
{
/// <summary>
/// Class used for encryption and decryption using AES algorithm
/// </summary>
public static class EncryptionProvider
  {
    /// <summary>
    /// Encrypt a string
    /// </summary>
    /// <param name="input">String to encrypt</param>
    /// <param name="password">Password to use for encryption</param>
    /// <returns>Encrypted string</returns>
    public static string Encrypt(string input, string password)
    {
      //make sure we have data to work with
      if (string.IsNullOrEmpty(input))
        throw new ArgumentException("input cannot be empty");
      if (string.IsNullOrEmpty(password))
        throw new ArgumentException("password cannot be empty");
      // get IV, key and encrypt
      var iv = CreateInitializationVector(password);
      var key = CreateKey(password);
      var encryptedBuffer = CryptographicEngine.Encrypt(
        key, CryptographicBuffer.ConvertStringToBinary(input, BinaryStringEncoding.Utf8), iv);
      return CryptographicBuffer.EncodeToBase64String(encryptedBuffer);
    }
    /// <summary>
    /// Decrypt a string previously ecnrypted with Encrypt method and the same password
    /// </summary>
    /// <param name="input">String to decrypt</param>
    /// <param name="password">Password to use for decryption</param>
    /// <returns>Decrypted string</returns>
    public static string Decrypt(string input, string password)
    {
       //make sure we have data to work with
      if (string.IsNullOrEmpty(input))
         throw new ArgumentException("input cannot be empty");
       if (string.IsNullOrEmpty(password))
         throw new ArgumentException("password cannot be empty");
       // get IV, key and decrypt
       var iv = CreateInitializationVector(password);
       var key = CreateKey(password);
       var decryptedBuffer = CryptographicEngine.Decrypt(
         key, CryptographicBuffer.DecodeFromBase64String(input), iv);
       return CryptographicBuffer.ConvertBinaryToString(
        BinaryStringEncoding.Utf8, decryptedBuffer);
    }
    /// <summary>
    /// Create initialization vector IV
    /// </summary>
    /// <param name="password">Password is used for random vector generation</param>
    /// <returns>Vector</returns>
    private static IBuffer CreateInitializationVector(string password)
    {
      var provider = SymmetricKeyAlgorithmProvider.OpenAlgorithm("AES_CBC_PKCS7");
      var newPassword = password;
      // make sure we satify minimum length requirements
      while (newPassword.Length < provider.SupportedKeyLengths.Min)
      {
        newPassword = newPassword + password;
      }
      //create vecotr
      var iv = CryptographicBuffer.CreateFromByteArray(
        UTF8Encoding.UTF8.GetBytes(newPassword));
      return iv;
    }
    /// <summary>
    /// Create encryption key
    /// </summary>
    /// <param name="password">Password is used for random key generation</param>
    /// <returns></returns>
    private static CryptographicKey CreateKey(string password)
    {
       var provider = SymmetricKeyAlgorithmProvider.OpenAlgorithm("AES_CBC_PKCS7");
       var newPassword = password;
       // make sure we satify minimum length requirements
      while (newPassword.Length < provider.SupportedKeyLengths.Min)
      {
        newPassword = newPassword + password;
      }
      var buffer = CryptographicBuffer.ConvertStringToBinary(
        newPassword, BinaryStringEncoding.Utf8);
      buffer.Length = provider.SupportedKeyLengths.Min;
      var key = provider.CreateSymmetricKey(buffer);
      return key;
    }
  }
}

Using this class is very easy. Here is the example from my sample WinRT application.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Data;
namespace EncryptDecrypt
{
partial class MainPage
  {
    public MainPage()
    {
      InitializeComponent();
    }
    bool encrypt = true;
    private void Button_Click(object sender, RoutedEventArgs e)
    {
       var password = this.password.Text;
       if (encrypt)
       {
          this.input.Text = this.input.Text;
          this.ouput.Text = EncryptDecrypt.EncryptionProvider.Encrypt(this.input.Text, password);
          this.button.Content = "Decrypt";
          encrypt = false;
      }
      else
      {
          this.input.Text = this.ouput.Text;
          this.ouput.Text = EncryptDecrypt.EncryptionProvider.Decrypt(this.ouput.Text, password);
          this.button.Content = "Encrypt";
         encrypt = true;
      }
    }
  }
}

As you can see, my sample test app just calls two main methods and shows the results of encryption and decryption. Password and input string are required and cannot be left empty.

I am hoping to expand this in the future, once documentation is more complete, but this suffices for now. Please feel free to comment on this, especially if you have more information on the subject.

Thanks.

Post to Twitter

VS Live Orlando

I will be speaking at VS Live conference in Orlando, FL on 12/08/2011. I will be presenting the following two talks.

Working with Data on Windows Phone 7
I will talk about various approaches to work with data on Windows Phone 7. I will cover all major concepts, such as local storage, OData/WCF Data Services and custom WCF services. I will demonstrate how to retrieve data and save changes locally or to a remove web server. I will build demos for all technologies step-by-step.

You will learn:
• About options to persist the data on Windows Phone 7
• About pros and cons of each technologies
• Knowledge to build a Windows Phone application that publishes and/or consumes data

You can download the materials for this presentation here.

Using Code First (Code Only) Approach with Entity Framework
Session will include high level overview of Entity Framework and how various approaches to use it fit into application development lifecycle. Then I will build POCO classes that entity framework can use to create database as well as perform CRUD operations against the database. Various attributes that are included out of the box will be covered. This will include columns constraints, relationships, etc. I will show you how ASP.ENT MVC 3 can utilize entity framework code first metadata to build automatic validation of user input.

You will learn:
• How to build data access layer with Entity Framework Code First
• About validation approaches using POCO classes
• Fluent API and attribute based configuration option

I hope to see you there. 

Thanks.

Post to Twitter

Update to WinRT Database project

If you follow my posts, you noticed that I started up WinRT database project on CodePlex.  I just published as small update to it that now support data binding to list based controls in WinRT.  It took actually a significant amount of pain and research, including some posts on WinRT forums.

You can read my post here on details of data binding to list objects in WinRT.  I used the code I posted there in my WinRT database projects.  I also started working on support for thread safety when working with file asynchronously.  This is not an issue for you if you have a Save button, but my goal is to eventually support transparent save, where data is saved automatically when it changes.

Comments are welcomed.

Thanks.

Post to Twitter

ObservableCollection<T> in WinRT

I have been learning WinRT, new Windows 8 run time for developing Windows 8 application for a little while now.  I am using my CodePlex project as study project.  One of my goals is have an ability to persist collections of object into file system, loosely called database.  I really want my collections to be bindable, so I attempted to use ObservableCollection<T> as the base class for my collections.  This worked just find in Windows Phone 7 and Silverlight based projects.  The same however does not hold true in WinRT.  It contains a number of bases classes that WinRT controls such as ListBox listen to instead of INotifyCollectionChanged.  Specifically, it is IObservableVector<T>.  There is a sample implementation in one of the WinRT sample apps, but I really did not like how it was done – via extension method on INotifyCollectionChanged.  What I really wanted to do is extend Observable Collection, because I think Microsoft will eventually have an implementation for IObservableVector<T>, maybe they would event extend the observable collection itself.  First thing I ran into is that if you use IObservableVector with T anything other than object, your program will throw “bad image” exception.  So, here is the outline of my solution.

  • Use Observable Collection as base class
  • Implement IObservableVector<object>

That should do it, right?

So, I am starting with this declaration:

public class ExtendedObservableCollection<T> : ObservableCollection<T>, IObservableVector<object>

Then I use smart tag for IObservableVector and let Visual Studio fill in the necessary interfaces I have to implement.  Then I simply call base methods of Observable Collection for the majority of implementation, casting object to T as necessary.  Simple and efficient, and most importantly, something I could simply remove down the road as WinRT API becomes more mature.  Here is the final class.

using System;
using
System.Collections.Generic;
using
System.Collections.ObjectModel;
using
Windows.Foundation.Collections;
 

namespace
WinRTDatabase.Core
{
   
/// <summary>

   
/// Class that works for data bindings for WinRT list based controls
   
/// </summary>
   
/// <typeparam name="T"></typeparam>
   
public class ExtendedObservableCollection<T> : ObservableCollection<T>, IObservableVector<object>
    {
 
       
/// <summary>

       
/// Raises collection changed event
       
/// </summary>
       
/// <param name="e">Event arguments for collection changed event</param>
       
protected override void OnCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
           
base
.OnCollectionChanged(e);
           
switch
(e.Action)
            {
               
case
System.Collections.Specialized.NotifyCollectionChangedAction.Add:
                    OnVectorChanged(CollectionChange.ItemInserted, (
uint
)e.NewStartingIndex);
                   
break
;
               
case
System.Collections.Specialized.NotifyCollectionChangedAction.Move:
                    OnVectorChanged(CollectionChange.Reset, (
uint
)e.NewStartingIndex);
                   
break
;
               
case
System.Collections.Specialized.NotifyCollectionChangedAction.Remove:
                    OnVectorChanged(CollectionChange.ItemRemoved, (
uint
)e.OldStartingIndex);
                   
break
;
               
case
System.Collections.Specialized.NotifyCollectionChangedAction.Replace:
                    OnVectorChanged(CollectionChange.ItemChanged, (
uint
)e.NewStartingIndex);
                   
break
;
               
case
System.Collections.Specialized.NotifyCollectionChangedAction.Reset:
                    OnVectorChanged(CollectionChange.Reset, (
uint
)e.NewStartingIndex);
                   
break
;
               
default
:
                   
break
;
            }
        }
       
protected void OnVectorChanged(CollectionChange collectionChange, uint
index)
        {
           
if (VectorChanged != null
)
            {
                VectorChanged(
this, new VectorChangedEventArgs
(collectionChange, index));
            }
        }
 
       
public event VectorChangedEventHandler<object
> VectorChanged;
 
       
public int IndexOf(object
item)
        {
           
return base
.IndexOf((T)item);
        }
 
       
public void Insert(int index, object
item)
        {
           
base
.InsertItem(index, (T)item);
        }
 
       
public new object this[int
index]
        {
           
get

            {
               
return base[index];
            }
           
set

            {
               
base[index] = (T)value;
            }
        }
 
       
public void Add(object
item)
        {
           
base
.Add((T)item);
        }
 
       
public bool Contains(object
item)
        {
           
return base
.Contains((T)item);
        }
 
       
public void CopyTo(object[] array, int
arrayIndex)
        {
            T[] newArray =
new
T[array.Length];
           
for (int
i = 0; i < array.Length; i++)
            {
                newArray[i] = (T)array[i];
            }
            CopyTo(newArray, arrayIndex);
        }
 
       
public bool
IsReadOnly
        {
           
get { return false
; }
        }
 
       
public bool Remove(object
item)
        {
           
if
(Contains(item))
            {
               
base
.Remove((T)item);
               
return true
;
            }
           
return false
;
        }
 
       
public new IEnumerator<object
> GetEnumerator()
        {
           
return base.GetEnumerator() as IEnumerator<object
>;
        }
    }
}

 

Thanks.

Post to Twitter

How to Improve Performance of CSLA for Silverlight

CSLA for Silverlight is using MobileFormatter class to serialize and de-0serialize the data that if sent across the wire during client/server communications.  General flow of the serialization process is as follows.  Each object that implements IMobileObject is being asked by mobile formatter to serialize its data into a list of SerializationInfo objects.  That list maintains the state of each object as well as the relationships between objects.  Ultimately, the data consist of simple properties serialized into FieldData objects and relationships between objects into ChildData objects.  The formatter then is using DataContactSerializer and XML Reader/Writer combination in order to create byte arrays from object data.  These byte arrays are just XML blobs when all said and done of SerializationInfo objects.  DataContractSerializer is doing the best job it can in order to specify enough information in the XML to make it possible to reconstruct the data on the other end of the wire.  As a result, it drops hints from XML standards that specify what primate type should be used for each property value of each objects.  This results in extremely verbose XML, where each property may take additional 20-30 bytes to specify the type to be used.  On top of that, CSLA is using descriptive names inside Serialization Info object as well as generic dictionaries to store ChildData and FIeldData objects.  Turns out, serializer puts enough metadata around generic collections as well that makes them larger.

So, we took a few steps to provide some optimization around the code that should work with any version of CSLA that has MobileFormatter.  First of all, we changed DataMember and DataContract attributes to provider shorter names.  For example, instead of Value property we will just have VU in the XML.  We also created helper dictionaries instead of using generic dictionaries in order to be able to specify names for items and keys, all consisting of 2 letter instead of 4-10 letter.  Also, we eliminated XML type hints by injecting a xmlns namespace into XML header containing the root namespace of XML standards with one letter alias, which will eliminate 20-30 bytes from each serialized property.

Your particular results may vary, but we saw overall improvements of 2-50 percent depending on the objects.  Since Mobile Formatter is also used to take snapshots of objects to support Cancel button (undo) functionality, you will also see memory improvements in your Silverlight application as well.

Please read the warning message at the end of the article before you decide to use this code.

You can download attached SerializationInfo and make changes to your version of CSLA.  You will also need to find the following method in MobileFormatter

public void Serialize(XmlWriter writer, object graph)

 

and replace it with the code below:

    public void Serialize(XmlWriter writer, object graph)

    {

      List<SerializationInfo> serialized = SerializeAsDTO(graph);

 

      DataContractSerializer dc = GetDataContractSerializer();

 

      dc.WriteStartObject(writer, serialized);

      writer.WriteAttributeString("xmlns", "z", null, "http://www.w3.org/2001/XMLSchema");

      dc.WriteObjectContent(writer, serialized);

      dc.WriteEndObject(writer);

    }

 

WARNING – the byte arrays are not going to be compatible with previous CSLA version.  So, if you are serializing objects using MobileFormatter and storing them somewhere, you will not be able to de-serialize them after you make the change.

You can also download SerializationInfo file here.

 

Post to Twitter

Quick Start for WinRT Database

 

I have a CodePlex project for file based database for WinRT / Windows 8. You can check out this project at http://winrtdatabase.codeplex.com/

First step is to download the project and build it on your computer. Visit the download page for the latest recommended download. Unzip the source code on your machine, open it up in Visual Studio 11 (Developer preview) and compile to create a DLL.

Next, create new Windows Metro style application project using C# and add a reference to the DLL from step 1.  You will end up with a XAML / C# based project.

Next, in your View Model (or elsewhere in your application) check for database existence and create if it does not exist along with tables. See sample code below

public async void Initialise()
        {

            var exists = await Database.DoesDatabaseExistsAsync(DatabaseName);
            if (!exists)
            {
                _database = await Database.CreateDatabaseAsync(DatabaseName);
                _database.CreateTable<Person>();
                var table = await _database.Table<Person>();
                table.AddRange(new Person[]
                {
                    new Person()
                    {
                        PersonID = Guid.NewGuid(),
                        FirstName = "Sergey",
                        LastName = "Barskiy",
                        Age=19
                    },
                    new Person()
                    {
                        PersonID = Guid.NewGuid(),
                        FirstName = "Michelle",
                        LastName = "Barskiy",
                        Age=18
                    }
                });
                await _database.SaveAsync();
                People = table;
            }
            else
            {
                _database = await Database.OpenDatabaseAsync(DatabaseName, true);
                var table = await _database.Table<Person>();
                People = table;
            }
        }

In the sample above I am testing if database exists, then create it if it does not, Then I am adding a table to it based on POCO class Person. I am adding two people to the tables.  You can add a single instance by calling Add instead of AddRange.  For example, Person class would look like

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.UI.Xaml.Data;

namespace WinRTDbQuickStart
{
    public class Person : BaseObject
    {
        private Guid personID;

        public Guid PersonID
        {
            get { return personID; }
            set { personID = value; OnPropertyChanged("PersonID"); }
        }

        private string firstName;

        public string FirstName
        {
            get { return firstName; }
            set { firstName = value; OnPropertyChanged("FirstName"); }
        }

        private string lastName;

        public string LastName
        {
            get { return lastName; }
            set { lastName = value; OnPropertyChanged("LastName"); }
        }

        private int age;

        public int Age
        {
            get { return age; }
            set { age = value; OnPropertyChanged("Age"); }
        }
       
       
    }
}

To remove, just issue remove command:

public void OnDelete(Person parameter)
      {
          if (parameter != null)
          {
              People.Remove(parameter);
              People.SaveAsync();
          }
      }

You can also remove and add a range of items based on condition.

People.RemoveRange((person) => { return (person.Salary >= 2); });

Make sure to call SaveAsync() on either database or a specific table to commit your changes.

You can also look in unit test project and quick start project that is distributed as part of the source code download for other API samples. There are a number of issue with the sample app due to differences between WinRT and .NET.  For example,ListBox is not listening to Observable Collection changes, instead there is IObservableVector<T> interface.  I am planning to implement those changes next.

Update 11/25/2011 – Issue with binding to ListBox has been fixed.  All tables are now bindable to list based controls.

Post to Twitter

Reading and Writing Files in WinRT

I started converting my Windows Phone database project to WinRT. If you read the description of that project, you see that it is using Isolated Storage. There is no Isolated Storage in WinRT, so I had to practically re-write the entire project, at least all parts that deal with persistence. I have a preview now available, but since there is no TFS integration yet in Visual Studio 11 Express preview, I am not quite ready to post the project to CodePlex yet, but I wanted to post it on my blog as early preview.

As part of writing the file access login, I wrote a couple of extension methods for StorageFile class, those that used to exist in .NET. Primarily, I am referring to WriteAllText and ReadAllText methods. It took a bit to figure those out, and I wanted to post my research here for other folks’ benefits.

Let’s take a look at the class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Storage;
using Windows.Storage.Streams;

namespace WinRTDatabase.IO
{
    /// <summary>
    /// Storage File extensions for reading and writing
    /// </summary>
    public static class StorageFileExtensions
    {
        /// <summary>
        /// Asynchronously write a string to a file
        /// </summary>
        /// <param name="storageFile">StorageFile to write text to</param>
        /// <param name="content">Text to write</param>
        /// <returns>Task/ void if used with await</returns>
        async public static Task WriteAllTextAsync(this StorageFile storageFile, string content)
        {
            var inputStream = await storageFile.OpenAsync(FileAccessMode.ReadWrite);
            var writeStream = inputStream.GetOutputStreamAt(0);
            DataWriter writer = new DataWriter(writeStream);
            writer.WriteString(content);
            await writer.StoreAsync();
            await writeStream.FlushAsync();
        }

        /// <summary>
        /// Asynchronously read a string from a file
        /// </summary>
        /// <param name="storageFile">StorageFile to read text from</param>
        /// <returns>Task/ void if used with await</returns>
        async public static Task<string> ReadAllTextAsync(this StorageFile storageFile)
        {
            string content;
            var inputStream = await storageFile.OpenAsync(FileAccessMode.Read);
            var readStream = inputStream.GetInputStreamAt(0);
            var reader = new DataReader(readStream);
            uint fileLength = await reader.LoadAsync((uint)inputStream.Size);
            content = reader.ReadString(fileLength);
            return content;
        }
    }
}

No color coding yet in VS 2011, sorry for black and white code.  As you can see right away, all file IO must be asynchronous in WinRT at some point.  In both methods I am getting a stream from the file, then creating either input or output stream, then using either DataReader or DataWriter I am getting or setting the content of the file.me

Another interesting aspect is that both methods are asynchronous, but using different return values.  Return value of Task will translate into void method when used with async keyword.  Return value of Task<string> will translate into just string when using with async keyword.

await file.WriteAllTextAsync(content);

or

string content = await file.ReadAllTextAsync();

Stay tuned to sample WinRT application that is using my WinRT database that is based on file system.

Post to Twitter

VS Live Redmond 2011

As I mentioned before, I presented at VS Live conference in Redmond, WA yesterday, 10/20/2011.  I presented the following two talks

Working with Data on Windows Phone 7
I will talk about various approaches to work with data on Windows Phone 7.  I will cover all major concepts, such as local storage, OData/WCF Data Services and custom WCF services.  I will demonstrate how to retrieve data and save changes locally or to a remove web server.  I will build demos for all technologies step-by-step.

You will learn:
• About options to persist the data on Windows Phone 7
• About pros and cons of each technologies
• Knowledge to build a Windows Phone application that publishes and/or consumes data

You can download the materials for this presentation here.

Using Code First (Code Only) Approach with Entity Framework
Session will include high level overview of Entity Framework and how various approaches to use it fit into application development lifecycle.  Then I will build POCO classes that entity framework can use to create database as well as perform CRUD operations against the database.  Various attributes that are included out of the box will be covered.  This will include columns constraints, relationships, etc. I will show you how ASP.ENT MVC 3 can utilize entity framework code first metadata to build automatic validation of user input.
 
You will learn:
• How to build data access layer with Entity Framework Code First
• About validation approaches using POCO classes
• Fluent API and attribute based configuration option

You can download the materials for this presentation here.

Post to Twitter

Setting Up Windows 8 On Virtual Machine

Today I decided to setup Windows 8 VM on my laptop to make it easier to convert my existing project for Windows Phone to WinRT.  The first one I wanted to update was isolated storage database.  So, I wanted to document my experience so that I could do it again if I need to.  There are some posts on the internet on how do it, but they seem to lack enough details, and I still had to figure a few things out.  So, here we go.

I decided to go with Oracle’s Virtual Box software to hos my VM.  I downloaded the latest version of it here, and it actually has an option for Windows 8 already.  I also downloaded Windows 8 Developer Preview with developer tools English, 64-bit (x64)8 ISO here.  Now I am ready to go.

First, install Virtual Box.  Process is painless and self-explanatory.  Now, run the software and create new machine:

image

Click next

image

Just pick Windows 8 as option and give your machine a name.  Click next

image

If you have a luxury of 8 GB or RAQM on your machine as I do, pick 4 GB.  You have to have at least 2 GB for decent enough performance.  Click next

image

Choose to create new disk and click Next

image

Pick your disk type, I went with default.

 

image

Fixed disk offers better performance, so I went with that.

image

Now pick disk size.  If you pick 20 GB, you will have about 5 GB left after you install the image.  Pick more if you would like.  You will get a warning later installing the ISO because it recommends more hard drive space, but it will install without issues anyway.  You can also pick a directory for the location of the disk file by clicking on folder icon (indicated by the hand cursor in my screenshot).  Click next

image

Click Create on the next screen.  The process takes a few minutes.

Once it is done, you have to mount the ISO on your virtual disk. Go to properties of you new VM and click on Storage (indicated by a hand cursor on screenshot below)

image

Click on CD icon next to DC/DVD drive label, select first option – Choose Virtual CD/DVD File and browse to your ISO image.  Then click OK.

 

image

Once you are back to Virtual Box window, highlight you new VM and click Start button.  Windows 8 install will start automatically, just follow the steps.  Voila, once it is done, you can run Windows 8 on your Windows 7 desktop.

A few final tips when running Windows 8 without touch.

  • To pull up charm for application search hit Windows key plus Q
  • To pull up the charm for settings hit Windows key plus I
  • To pull up desktop hit Windows key plus D

I will post on my experience converting WP 7 project to Win RT in a week or so  when I am back from speaking at VS Live next Thursday.

Thanks.

Post to Twitter

Code Mastery Event

I participated in Code Mastery event yesterday.  The event was put on by my company Magenic as an all day free community training event.  It was all about CSLA.  The author if this widely used framework, Rocky Lhotka himself was in attendance.  He presented on two topics.  Yours truly spoke on CSLA and XAML technologies.  I talked about advantages on CSLA in XAML world, and documented big code savings that CSLA brings to the table.  I am planning to upload my project to CSLA web site in the next few days, as there have been some requests to show how to use CSLA in conjunction with Prism to build Silverlight or WPF applications.  I will blog once that happens, and you should be able to take advantage of that sample.  The sample is using an extensive technology stack, including Entity Framework Code First, CSLA, Prism for Silverlight, SQL Server.  You can download PowerPoint presentation here.

Thank you.

Here is the full agenda of the event.

1. CSLA .NET intro – Rocky Lhotka

Topic will give attendees a high level overview of CSLA as an application framework. Key moving parts of CSLA will be covered, along with answering the most important question: Why use CSLA? Roles of business objects, data portal, rules, authentication and authorization will be covered in principal.

2. Business object design – Eric Blackwell

Session will concentrate of best practices for designing business objects. Single responsibility principal and maintainability will be covered in light of using CSLA. Key aspects of good CSLA business layer will be covered in detail, including properties, rules, data portal, data access, business method and validation. Particular attention will be paid to structuring classes and relationship between classes. Designing based on use cases will be an important aspect of the session.

3. Business, validation, and authorization rules – Tim Price-Williams

This session will be a deep dive into the world or rules. Topics such as validation rules, user authentication and authorization will be covered. Distinction between validation and business rules be drawn. Important key scenarios will be covered, such as synchronous and asynchronous rules, client / server rules, object creation and save scenario from rules perspective. Custom and built-in rules be covered in detail. A pattern for typical business rule/methods will be illuminated.

4. Data portal and n-tier architecture – Rocky Lhotka

This topic will cover in details all possibilities that CSLA provides when abstracting communication channels between client and server components. Difference between local and remote data portal will be discussed. Various configuration patterns will be highlighted along with usage scenarios for each one. Multi-tier deployment as it relates to data portals will be covered, as well as using external data sources instead of CSLA data portal in client only scenarios.

5. Data access – Travis Brown

This session is all about data access technologies and how they relate to CSLA data portal access. The topic will include patterns for abstracting data access for business objects to promote maintainability. Discussion of Microsoft technologies for data access will take place as well.

6. XAML and MVVM – Sergey Barskiy

This session will concentrate on using CSLA as business layer in XAML based user interfaces. Taking Silverlight as an example, session will highlight how CSLA base classes can be used to facilitate communication between UI and business objects. Adaptability of CSLA business layer to seamlessly alter user interface based on rules be will covered. Patterns for wiring business objects for Silverlight environment will be part of the discussion.

7. ASP.NET MVC – Mitch Gordon

This session will concentrate on using CSLA as business layer in ASP.NET MVC based user interfaces. The discussion will include CSLA provided base classes that will allow developers write less code. The session will illuminate patters for maintaining authentication and authorization rules between server calls. Patterns for adapting UI based on user rights will be discussed.

Update 10/12/2011

Rocky wrote a blog post about the event that includes a link to a downloadable file with all the material enclosed.  You can find the blog post here.

Post to Twitter

Code Mastery Event

I am going participate in Code Mastery event that Magenic is sponsoring next week, on October 8th.  Code Mastery is a series of community events that my company puts out to help developers learn more about various programming topics.  The upcoming event in Atlanta is dedicated to CSLA.NETRocky Lhotka, author of CSLA will be coming to Atlanta to speak at the event.

You can register for Code Mastery here.

Our agenda consists of the following topics.

Sessions:

1. CSLA .NET intro – Rocky Lhotka

Topic will give attendees a high level overview of CSLA as an application framework. Key moving parts of CSLA will be covered, along with answering the most important question: Why use CSLA? Roles of business objects, data portal, rules, authentication and authorization will be covered in principal.

2. Business object design – Eric Blackwell

Session will concentrate of best practices for designing business objects. Single responsibility principal and maintainability will be covered in light of using CSLA. Key aspects of good CSLA business layer will be covered in detail, including properties, rules, data portal, data access, business method and validation. Particular attention will be paid to structuring classes and relationship between classes. Designing based on use cases will be an important aspect of the session.

3. Business, validation, and authorization rules – Tim Price-Williams

This session will be a deep dive into the world or rules. Topics such as validation rules, user authentication and authorization will be covered. Distinction between validation and business rules be drawn. Important key scenarios will be covered, such as synchronous and asynchronous rules, client / server rules, object creation and save scenario from rules perspective. Custom and built-in rules be covered in detail. A pattern for typical business rule/methods will be illuminated.

4. Data portal and n-tier architecture – Rocky Lhotka

This topic will cover in details all possibilities that CSLA provides when abstracting communication channels between client and server components. Difference between local and remote data portal will be discussed. Various configuration patterns will be highlighted along with usage scenarios for each one. Multi-tier deployment as it relates to data portals will be covered, as well as using external data sources instead of CSLA data portal in client only scenarios.

5. Data access – Travis Brown

This session is all about data access technologies and how they relate to CSLA data portal access. The topic will include patterns for abstracting data access for business objects to promote maintainability. Discussion of Microsoft technologies for data access will take place as well.

6. XAML and MVVM – Sergey Barskiy

This session will concentrate on using CSLA as business layer in XAML based user interfaces. Taking Silverlight as an example, session will highlight how CSLA base classes can be used to facilitate communication between UI and business objects. Adaptability of CSLA business layer to seamlessly alter user interface based on rules be will covered. Patterns for wiring business objects for Silverlight environment will be part of the discussion.

7. ASP.NET MVC – Mitch Gordon

This session will concentrate on using CSLA as business layer in ASP.NET MVC based user interfaces. The discussion will include CSLA provided base classes that will allow developers write less code. The session will illuminate patters for maintaining authentication and authorization rules between server calls. Patterns for adapting UI based on user rights will be discussed.

 

I hope to see you there.

Post to Twitter

EF Extras Project Update

Following the roadmap of my newest CodePlex project EF Code First Extras, I implemented support for default values as part of code-free migrations of SQL Server.

Default values is something that is necessary in order to support migrations.  If you are adding a new column to the table that does not allow nulls and you do not provide default value, your migration will fails.

I followed very simple code path in order to implement support.  I added default attribute to the project, and the users can simply add this new attribute to their classes in order to set default values in the database.  Attribute has two overloads – one that only takes default value as string, the other allows you to specify table and column name in addition to default value.  The reason for the second overload is the fact that some of the built-in configuration are not available to us, so if somebody changes table name via configuration, there is no way for the system to get to this information.  I do support however Table and Column attributes.

For example, let’s take a look at the following class:

    [Table("MyChair")]
   
public class Chair

    {
       
public int ChairID { get; set; }
       
public string Description { get; set
; }
 
        [
Column("ChairHeight"
)]
        [
Default("10"
)]
       
public decimal Height { get; set
; }
 
        [
Default("GetDate()"
)]
       
public DateTime DateAdded { get; set
; }
    }

 

As you see, I changed the table name, using MyChair instead of class name of Chair.  I also changed a column, using ChairHeight instead of property name of Height.  Default subsystem handles both use cases, applying the default value of 10 to the column.  As you also see, I support functions, such as GetDate(), so the newly added column DateAdded will be populated with current date/time value.  System if very flexible as you can see.  Of course, you can leave all name as is, and use much simpler code:

    public class Person
    {
       
public int PersonID { get; set; }
       
public string PersonName { get; set
; }
        [
Default("1"
)]
       
public bool IsActive { get; set
; }
        [
Default("People", "Salary", "1100"
)]
       
public decimal Salary { get; set
; }
    }

 

Above, the default for IsActive column could not be simpler.  The default for Salary column explicitly specifies table and column name for the reason I described above.

Very easy and intuitive interface, if I have to say so myself.

Please let me know your questions.  As always I appreciate any suggestions.  You can download updated source code off CodePlex site.

Post to Twitter

Pluralization in Entity Framework

As I am working on my Entity Framework extras project, I found myself needing to determine table name in the database based on class name used with DbSet in my context.  I was unable to find a way to query entity framework for this information, so I resorted to brute force approach, having to query database based on class name or pluralized class name.  I ready this blog post by Scott Hanselman about pluralization.  However, this class has been made internal, and I could not use it directly.  Having enough experience with reflection, I wrote a wrapper class that used internal class via reflection.  This code will break if API changes, but the fix at that point should be trivial.  The code of course is super easy, and looks as following:

    public static class Pluralizer
    {
       
private static object _pluralizer;
       
private static MethodInfo
_pluralizationMethod;
 
       
public static string Pluralize(string
word)
        {
            CreatePluralizer();
           
return (string)_pluralizationMethod.Invoke(_pluralizer, new object
[] {word});
        }
 
       
public static void
CreatePluralizer()
        {
           
if (_pluralizer == null
)
            {
               
Assembly aseembly = typeof(DbContext
).Assembly;
               
var
type =
                    aseembly.GetType(
                       
"System.Data.Entity.ModelConfiguration.Design.PluralizationServices.EnglishPluralizationService"
);
                _pluralizer =
Activator.CreateInstance(type, true
);
                _pluralizationMethod = _pluralizer.GetType().GetMethod(
"Pluralize"
);
            }
        }
    }

 

As you can see, I am loading assembly class by picking a random class from Entity Framework assembly, DbContext in my case.  Then I am getting a type corresponding to English pluralization service.  Once that is done, I am getting a handle of Pluralize method based on name.

Pretty easy, hah?  Here is how I am testing (using) my new class:

        [TestMethod]
       
public void
PluralizationTest()
        {
           
Assert.AreEqual("people", Pluralizer.Pluralize("person"
));
           
Assert.AreEqual("people", Pluralizer.Pluralize("people"
));
        }

 

Ah, the magic of reflection!

Post to Twitter

Windows 8 Metro Sample Applications

You can download a number of samples for Metro style applications from MSDN Code site. 

http://code.msdn.microsoft.com/Windows-Developer-Preview-6b53adbb

Enjoy.

Post to Twitter

What I learned at the Build Conference

I returned from Build conference Friday night.  It was a really exciting conference in my opinion with a lot of new ideas revealed.  Microsoft had kept a very tight lid on upcoming changes for many months, and none really knew what was going to be announced at the event.  There were a number of speculations, but nothing concrete showed up on the internet.  The only exception was a 5 minute video that was put out by Microsoft a few months back, giving viewers a glimpse of the new operating system, Windows 8.  In retrospect, I cannot disagree with Microsoft decision, as the changes that were announced are designed to differentiate Microsoft as an operating system provider, thus giving revealing the information prematurely would lessen a competitive advantage over rivals.

So, what was unveiled at the conference?  Microsoft demonstrated in a significant level of details its new operating system, Windows 8.  At the high level, its user interface carries over the investments Microsoft has made in the area of design for Windows Phone 7.  Windows 8 conforms to Metro design principles.  The opening screen in Windows 8 is very similar to Windows Phone 7, consisting of a number of live tiles, grouped into a number of areas.  Those groups are user defined, and this was demonstrated as well.  User will be able to use gestures of course to control the appearance of the OS.  They will be able to zoom out of the detailed view, find a group they are looking for, and zoom back into that group.  Of course they will also be able to re-arrange any part of any group or groups themselves using similar gestures to the ones on the phone.  What about old look and feel you ask?  The new OS is built on top of Windows 7, and one can drop back to classical look and feel by clicking on Desktop tile. 

There are also a number of new features that exist in Windows 8.  One of them is “charms”.  Charms are located in the right hand area of the screen, and are typically hidden.  The user can bring them into view by swiping from right hand edge to toward the center of the screen.  Charms are common features to all the programs, such as printing, devices, networking, sharing, search, etc.  All software written for Windows 8 should incorporate these charms to provide seamless user experience.  Not only charms allow developers to integrate their applications deeply with Windows 8 OS, but also with each other.  There is a number of contracts in WinRT that one application can implement, that other applications can utilize.  For example, you can write a photo editor application, that implements search contract, and another application such as family tree can search photos and show them in its UI.  Pretty cool, hah?  Similar contracts also exist for devices such as printer.

Now let me talk about programming for Windows 8.  Developers will be able to use C#/VB.NET, C++ and JavaScript to write Windows 8 applications.  Sounds strange at the first sight doesn’t it?  Beforehand browser based application were not able to reach deeply into operating system.  This broad functionality is being enabled view new Windows runtime for writing applications, WinRT.  Unlike .NET, this new run time is built into Windows itself, and it not an additional layer on top of existing Windows functions, as it is the case with .NET.  As a result, WinRT will have better performance.  To ensure highly responsive applications, all the functionality in WinRT that is not instantaneous contains asynchronous methods.  This would include things such as file I/O, networking operations, such as internet client, etc.  I heard phrase “fast and fluid” to describe Windows 8 UI and applications dozens of times during the conference.  Of course, not everything is contained within WinRT, thus .NET is also an integral part of building applications for Win 8.  As a matter of fact, new version of Microsoft.NET, 4.5 will ship with Windows 8, and will be available as part of the operating system.  There is a difference however between traditional .NET and new Metro style applications.  When a developer builds Metro applications, only a subset of .NET is available to this person.  For example, file IO functionality is greatly limited in preference to new WinRT pickers.  These pickers such as open file or save file pickers replace traditional IO in favor of safer and asynchronous operations, where entire file system is not exposed to a Metro style application.  You get the idea right?  Metro apps run in a sandboxed environment.  So, if you want to build Metro apps, you will use .NET and WinRT, but your tooling will remain the same.  You will use Visual Studio v. next and your favorite language to build those applications.  What about UI, you ask?  You have options there as well.  If you opt for JavaScript as your language of choice, you build UI in HTML.  If you pick C#, VB.NET or C++, you will build UI for your applications in XAML.  No, not Silverlight or WPF, but XAML.  Your XAML skills transfer over, but namespaces you used will change.  There will also be some new controls, such as GridView and FlipView.  If you ever saw Windows Phone 7 applications, you understand that in order to enable Metro style UI and more importantly touch based UI, you need new set of controls, and Windows 8 is all about touch interfaces. 

A few words about legacy software.  Microsoft pledged that all the software that successfully ran on Windows 7 will run on Windows 8.  This would include platforms such as WinForms, WPF, Silverlight, HTML, etc.

There were a number of devices shown that will run Windows 8.  In addition to tablets, laptops and PCs, which all will incorporate traditional processors and likely solid state hard drives, there will be another class of lighter devices, running Windows 8 on RISC processors.  This is drastically different from Apple’s approach that uses different OS for tablets.  As a result, Microsoft tablets will be more functional, and will contains software such as Microsoft Office and other PC based applications. 

New version of Visual Studio, Expression Blend and Microsoft.NET will all ship to help developers build Metro style applications.  Visual Studio will contain templates for Metro apps, Expression Blend will enable UI design, but not just XAML.  Blend gets new set of functionality, enabling it to design HTML as well.  Cool new editing features found their way into Blend.  Because Blend actually runs your XAML and HTML, you actually see your applications running with data.  All changes you make will update either XAML, HTML or even CSS in your Visual Studio project.  Visual Studio got new XAML designer.  It appears that old designer code name Cider is gone, and is replace with Blend designer!!!  Yeah, it is about 4 times faster now.  Personally, I always hated Cider’s performance and hardly ever used XAML view in studio because of that.  Power tools for studio previously available on NuGet only, will be integrated into Studio directly when it ships.

Another huge news that will interest developers is new Windows 8 App Store.  If you create Metro style application, you will be able to sell it through new app store.  I can only guess that the model will be largely similar to Windows Phone 7 app store.  Potential market though is thousands of times larger.  According to Microsoft, Windows is being run on almost half a billion computers.  If you can imagine, one dollar app can make you a millionaire.  Not that this will happen to too many people, but the promise is certainly there.

Another software release was announced, and that is TFS in the cloud service from Microsoft.  Beta has been released, and attendees all got beta account free of charge. 

Live Services will be an integral part of Windows 8.  It looks like SkyDrive will enable many cool features, such as roaming profiles that will enable users to have exact same desktop on many computers.  Developers will be able to use that feature as well, roaming state of their software across multiple computers, for example making sure that users of a software have the same state of the software available on all machines.

 

In summary, here is are the most important points (IMHO).

  • Windows 8 is all about modern consumer experience.  This includes touch based Metro UI.
  • Developers carry all their existing skills over to Metro applications, including XAML, .NET languages, .NET Framework, HTML and JavaScript. 
  • NET is not dead Smile, it is integral part of Metro applications along with WinRT.
  • Developers get to utilize new WinRT, making applications faster and highly integrated with OS and each other.
  • New tools will be shipped to enable developers to create applications faster with a uniform look and feel.
  • Money making opportunity is there for all developers.

You can watch all the online content, including keynotes and sessions, from the conference on www.BuildWindows.com

Please let me know if you have any questions, I would like to kick off a discussion that would benefit all of us, including me.

Post to Twitter

Impressions From Build Conference

Today was the first day of the Build Conference in Anaheim.
I wanted to type my notes before going to bed.
First of all, I am typing this blog post on my brand new Windows 8 tablet. No MS Word on it, so forgive all the typos.
The day started with key note. You can watch it on www.buildwindows.com
I thought all the demos were quite impressive. Windows 8 is totally following the footsteps or windows phone 7, fully embracing Metro design principles. Not really a surprise that I liked that a lot, since I really like my windows phone. A variety of devices were on the stage, stressing the fact that windows 8 will run on all of them, including tablets. The same coded base on all them, The same apps will run on all the devices then, right?
Coding experience included C++, C#, VB.NET, JavaScript/HTML, XAML. No, not Silverlight, just XAML. Seems very similar to Silverlight to me. All of these approaches rely on new runtime, WinRT. All the apps use this new run time to utilize features in Windows 8. Unlike .NET, this run time is part of Windows, optimized for performance. Visual studio is the tool that will be used to build applications that use this run time. It comes with a number of project templates that make it easy to write applications that fit naturally into Metro style. This includes look and feel, but also animations and styles.
I am not quite clear what happens to .NET in this brave new world.
We will just have to wait and see.

Post to Twitter

Update to EF Code First Extras Project

Today I issued an update to my Code Plex project that will contain a number of extras for Entity Framework Code First based applications.  You can find the project here.

I added repository project to the solution, containing base repository classes.  I had time analyze the problem some more and decided to make a few changes to the code I blogged about previously.  You can read my posts here and here.

To make the code cleaner, I decided to separate read and write patterns / code bases.  So, if someone does not like my Select implementation, you can create your own methods to select the data, but still can inherit from Write Repository to take advantage of CUD methods.

Please open unit tests project in the solution to see both select and update/inert/delete code.

Please let me know you questions, I am would like to improve my code.

Thanks.

Post to Twitter

Silverlight’s KeyUp Event and Backspace

Surprisingly enough, I never ran into this issue, event though I worked with Silverlight for three years now.  The specific issue is that some keyboard events are not echoed in KeyUp events.  For example, if you subscribe to KeyUp in a textbox and you hit Backspace key, KeyUp event does not fire.  This is quite inconsistent in my opinion.  The reason this happens is because the event is trapped by Silverlight, processed independently and marked as Handled, so it does not bubble up to the textbox.  You can see some workarounds on the internet, most involving inheriting from a textbox.  I do not particularly like this answer because it involves a lot of work on my part.

So, I wanted to blog about functionality in Silverlight that is not widely known, but I used on a few occasions.  Specifically, it allows developers to receive events that have been marked as handled elsewhere.

I am referring to AddHandler function.  Here is typical syntax:

Element.AddHandler(UIElement.KeyDownEvent, new KeyEventHandler(Element_KeyDown), true);

Element.AddHandler(UIElement.KeyDownEvent, new KeyEventHandler(Element_KeyUp), true);

The key is the last parameter to AddHandler.  It signals to Silverlight to inform you of the events even though they have been marked as handled.  You would use this call instead of

Element.KeyUp += Element_KeyUp;

You can read more about this function here.

Enjoy.

Thanks.

Post to Twitter

Entity Framework Migrations

I recently posted on my intentions to create a migration solution for Entity Framework Code First using Red Gate tools.  The initial alpha version 0.9 is now live on CodePlex.  Here is how you would use the product. 

You have to obtain a license to Red Gate SQL Comparison SDK.  If you simply would like to try my solution, just get 14 days trial and check out what it does for you.  In my opinion, $700 dollars is not that much money for the functionality you get.  But of course, if you are giving your product away, that is a lot of cash.

Next you have to create some classes to use.  Your table classes are the same as in any other code first project.  You context however, now needs to inherit from ExtendedDbContext from my project.

    public class ProductsContext : ExtendedDbContext
    {
       
public ProductsContext(string connectionString)
            :
base
(connectionString)
        {
 
        }
 
       
public DbSet<Product> Products { get; set
; }
 
       
public DbSet<DbVersion> Version { get; set
; }
 
       
protected override void OnModelCreating(DbModelBuilder
modelBuilder)
        {
           
            modelBuilder.Conventions.Remove<
IncludeMetadataConvention
>();
           
base
.OnModelCreating(modelBuilder);
            
        }

 

There is one requirement, you must have a constructor that takes connection string.  You would typically have something like that anyway, so this is a minor adjustment to make.

Next you have to decide how you are going to use version comparison.  I have an interface that you must implement INewVersionProvider<TContext>.  I provide two of those out of the box, which should be enough for you to get started.  I have AssemblyBasedNewVersionProvider and ModelBasedNewVersionProvider.  Frist one stores version of the assembly that contains your DbContext and uses it for comparison.  To trigger migration you have to bump up a version of your assembly before running or deploying.  Second one uses the same mechanism as Entity Framework, creating a model hash based on actual context definition and its tables.  There is one requirement you have to use to support versioning of migrations.,  You have to include DbVersion table which is part of my framework in your context.  You can see that above in this blog in my context definition. 

Next you have to implement MigratingInitializer.  I am including base class, making this process a breeze. 


using EFUtil.Migrations.SqlServer;
using
EFUtil.Migrations;
 

namespace
EFUtil.Tests.Source
{
   
public class ProductInitializer : MigratingInitializer<ProductsContext
>
    {
       
public ProductInitializer(INewVersionProvider<ProductsContext
> versionProivider)
            :
base
(versionProivider)
        {
 
        }
 
       
protected override void BeforeMigration(ProductsContext
context)
        {
 
        }
 
       
protected override void AfterMigration(ProductsContext
context)
        {
 
        }
    }
}

 

As you can see, I provide two hooks, before and after that will allow you to massage the data before the migration or after, including adding seed data.  You can use either context or manual queries. 

using EFUtil.Migrations;
using
EFUtil.Migrations.SqlServer;
using
System.Data.Entity.Infrastructure;
 

namespace
EFUtil.TestApplication
{
   
public class ProductInitializer : MigratingInitializer<ProductsContext
>
    {
       
public ProductInitializer(INewVersionProvider<ProductsContext
> versionProivider)
            :
base
(versionProivider)
        {
 
        }
 
       
protected override void BeforeMigration(ProductsContext
context)
        {
           
var adapter = context as IObjectContextAdapter
;
           
if
(context.Database.Exists())
                adapter.ObjectContext.ExecuteStoreCommand(
"Update Products Set ProductNumber = ProductNumber + ’1′"
);
        }
 
       
protected override void AfterMigration(ProductsContext
context)
        {
           
var adapter = context as IObjectContextAdapter
;
            adapter.ObjectContext.ExecuteStoreCommand(
"Update Products Set ProductName = ProductNumber + ‘ name’"
);
        }
    }
}

 

In the example above I am firing SQL Queries, but I could have added rows to context’s tables directly and fired Save().

I am also including conventions, just like I promised.  You can read more about conventions in my posts on global conventions and attribute conventions.  I also created a follow up post here.  All the code to support conventions is now part of CodePlex project.  I felt it is necessary to formalize my efforts in order to make the functionality cleaner and include tests for it.

If you download source code, you will see unit test project.  Note: you have to run one test at a time because there is a timing issue related to dropping databases.  There is also a quick test bed project you could use to play with code.  it is called EFUtil.TestApplication.  You can just keep altering Project class and re-running the project to observe migrations in action.

This is initial version, and I already have plans to further develop the functionality.

Here is my road map for the project:

  • Publish beta releases once I have some feedback and a number of downloads without bugs reported.
  • I am planning to add
    • Index support
    • Default values support

Please let me know what you think about my efforts and provide some feedback.

Post to Twitter

Entity Framework Thoughts

I have been thinking for a little while about the future of Entity Framework, feature set on the horizon, and trying to ascertain where I would like to concentrate my next “free time” project.

If you have not been keeping up with Entity Framework, please read the last few posts on the Entity Framework design blog about the present and the future of the product.

The more I have been thinking the more I see a benefit in creating a complementary solution that would enhance features available in Entity Framework, and possibly gather some community input as to what features are most needed.  Just like a number of folks, I looked at the migrations feature outline that will likely be using existing database project API.  I worked with database projects for quite some time, and I am not a giant fan of the product.  I did submit a handful of suggested enhancements, but I am not sure now if any of them will see a light of day.  API that the project exposes is different from Visual Studio UI of course, and I am sure that API will be good to write migration code against.  On the other hand, I worked with Red Gate product called SQL Compare and related .NET SDK since about 2005 on and off.  When I used that product last, our company saved countless amounts of money by using Red Gate API to synchronize our product database with existing databases in the field.  You can read more about SQL Compare here and SDK here.  You can also buy both products as a bundle.  If you look at the price of SDK, it is about $700 per developer, and it includes 10 distribution licenses.  I encourage you to read more about licensing process and maybe even call Red Gate, if you decide to use the product.  There is also a competing product from APEX.  You can read more about that product here.

But back to Entity Framework.  I confess, I have been a fan of the product since 1.0 beta.  I used it on production projects, and I saved countless hours not having to code stored procedures and DAL layers.  I became quite excited when Code First came out on top of 4.0 version.  It offered very clean programming interface with a number of options to handle many use cases that developers might have.  It did lack a few features, namely migrations, pluggable conventions, indexes, and default values.  I have been thinking about how to address this, given that I am not a Microsoft employee.   After thinking about it for quite some time, I decided to start a CodePlex project in attempt to address these issue on my own.  I am going to rely on Red Gate based on my expedience with the product and the fact that the price is right in my opinion.

Stay tuned for the announcement.  I suspect that the initial alpha version that would include migration story will be out in a few weeks.  I am going to “productize” my blog posts on pluggable conventions and roll them into the same CodePlex project next.

I am welcoming any suggestions, including your thoughts on buying $700 product.

Thank you.

Post to Twitter

VS Live Redmond

I am going to be speaking at VS Live conference in Redmond this year.  If you never attended this conference, I encourage everyone to do so.  You will have a week packed with sessions covering a variety of topics presented by top-notch developers.

As a speaker, I get a promotional code to give to anyone who registers before September 7.  You can use code VRSPK2 to get a ticket discount to the conference.  You can click on the link below to go straight to registration page with the discount code prefilled.

https://www.1105events.com/VisualStudioLive/2011Redmond/registration/reg_general_discount.php?priorityCode=vrspk2

I hope to see you there.

General Conference Information:

Visual Studio Live! Redmond

The Commons @ the Microsoft Redmond Campus

October 17-21, 2011

Event web site: http://vslive.com/redmond

Visual Studio Live is five days of practical, Microsoft-sponsored training for developers to help solve your tough .NET development challenges. You’ll find how-to advice and the tips and tricks that you’ll be ready to implement as soon as you get back to the office. Our expert faculty – including many Microsoft instructors – makes each session interactive so you can discuss your particular development roadblocks and come away with actionable solutions.

Visual Studio Live! Redmond offers in-depth training in:

  • Silverlight / WPF
  • Programming Practices
  • Visual Studio 2010 / .NET 4
  • Cloud Computing
  • Data Management
  • Web / HTML 5
  • Simplification Tools
  • Mobile Development

Visual Studio Live! Redmond – Expert Solutions for .NET Developers

Post to Twitter

Update for WP7 Database

I have had a small number of requests to enhance the functionality of my Windows Phone 7 database project on CodePlex.  In light of Mango release for WP 7 that will contain SQL CE database, I think that my project will likely be used less in just a few months.  The reason being is that once the users update, the reason to use Isolated storage to persist data becomes less appealing.  I am not knocking on my own project, I am just recognizing the reality.  Having said that, the database will likely still be in use for a while, since we have to wait for the actual phone users to update the version, which cannot be done via 3G, you have to use Zune to update.  Because of that, I think, I decided to implement the most request feature, specifically named tables.  In other words, right now you can create a table in my database and give it a type of data to store, such as :

db.CreateTable<Person>();

 

What named tables allow you to do, is horizontally partition your data by allowing multi0ple tables to store the same type, such as:

string name2 = "p2";
Database db = Database.CreateDatabase("test"
);
db.CreateTable<
Person
>(name1);

 

So, the syntax pretty much remains the same, so anywhere you used to refer to db.Table<T>, you can now also use db.Table<T>(tableName).  This includes all functions, such as adding of rows and querying.

db.Table<Person>(name1).Add(NewRandomPerson());

 

Nothing else changes.  One thing to notice, that this is pretty deep change that required me to touch a lot of code and test legacy data to ensure it opens properly.  As always, I did my due diligence, as you can gather from the tiny number of reported issues in over a year of usage.  Nevertheless, I encourage everyone to thoroughly test your applications.  You can open up my test project and see how I tested legacy data by looking at the method NamedTablesLegacyTest in my test page in test project.  As a result, I am going to publish this release under alpha version until I get some feedback that is sufficient enough to warrant beta status.

I made another small change, making DoesTableExist method public.

Enjoy.

Thank you.

Post to Twitter

Silverlight and Self-Hosted WCF

I have been working on a project that is based on Silverlight.  It is a large application that performs a variety of tasks, but also needs local access.  Basically, it needs access to scanner in order to scan and upload documents up to the data store.  I had an idea to create a WPF tray application that hosts a WCF Service that Silverlight application can talk to.  Because of WCF restrictions in Silverlight, you have to enable cross domain access in self-hosted WCF service.  There is a variety of posts on the subject, so I am not going to rehash the steps.  You can for example ready about that here.

I thought I came up with a pretty clean solution, and it got tested and worked great.  However, when we deployed it to a customer computers, we had intermittent problems with it.  It worked on soma machines, but did not on others.  We were trapping the errors, and it was reported as cross domain error even though we had all the correct code there to make it work.  Quite a puzzle.  One specific client was running IE 6, and our application was using https.  I pondered on the topic for a while, and on a hunch I added our site to the list of trusted sites in IE.  Voila, the error went away.

I wanted to blog about it, because I could not find anything on the internet that reports the same issue and the same fix.

Thanks.

Post to Twitter

More Changes to Calendar Control for WP 7

In the spirit of further improving my calendar control for Windows Phone 7, I added ability to show week number in the first column of the calendar control.

image

As you can see, the very first column can show week number,.  If course, I cannot break existing functionality, so the feature is disabled by default.  You can enable it by setting appropriate property on calendar control, called WeekNumberDisplay.  It has three options:


namespace WPControls
{
 
   
/// <summary>

   
/// Option of how to display week numbers in the calendar
   
/// </summary>
   
public enum WeekNumberDisplayOption
    {
       
/// <summary>
       
/// Do not show week number
       
/// </summary>
        None = 0,
       
/// <summary>
       
/// Show week number starting with start of the year
       
/// </summary>
        WeekOfYear = 1,
       
/// <summary>
       
/// Show week number starting with start of month
       
/// </summary>

        WeekOfMonth = 2
    }
}

 

So, you have options to show week of the year, week of the month or none.  Week of the month is simply number that starts with 1.  As far as week of the year goes, I am using built in functionality to properly determine this using localization rules as follows.

var systemCalendar = System.Threading.Thread.CurrentThread.CurrentCulture.Calendar;
weekNumber = systemCalendar.GetWeekOfYear(
  item.ItemDate,
  System.Threading.
Thread
.CurrentThread.CurrentCulture.DateTimeFormat.CalendarWeekRule,
  System.Threading.
Thread
.CurrentThread.CurrentCulture.DateTimeFormat.FirstDayOfWeek);

 

You can use this code any time you need to determine week number.

You can visit the home page for calendar control to download the latest source code.

http://wpcontrols.codeplex.com/

Thank you and keep the suggestions coming.

Post to Twitter

Update to Calendar Control for Windows Phone 7

Today due to numerous requests (technically one request from one person Smile), I updated my CodePlex project for calendar control for Windows Phone 7 – http://wpcontrols.codeplex.com/.

I added gesture support to the project.  You can now swipe (flick) from side to side to increment or decrement month, and swipe top to bottom and back to increment or decrement year.

I thought it was a very good enhancement idea that feels very natural to me to support on Windows phone.  I used XNA libraries to enable this support, and it only required a few lines of code.  To enable support you will need to set property on the calendar control – EnableGestures – to true.

Please let me know if you have any feedback.

Thanks.

Post to Twitter

Client and Server Side Validation in MVC 3

In this post I would like to examine how to create integrated client and server side validation in MVC 3.  The example is a bit contrived, but here is the just of it.  I have a person class and I want to make sure that email address does not contain first or last name and also cannot be longer than 50 characters.  Here is why I picked this example.  I want to be able to pass in value (maximum length) and also create parallel client / server side validation that enforces this rule.  This rule will dynamically get the values from last and first name fields and compare it to email field.  OK, now that the goal is stated, time to work on implementation.

First, let’s work on server side.  We can never trust the client, so server must enforce all client rules again.  Server side coding is very easy and can be easily accomplished via an attribute.  There is already a number of attribute, such as Required that we can use, but I want to create a custom rule in this case.  So, I will create brand new attribute, and take advantage of existing MVC functionality by inheriting from ValidationAttribute.  To make it more versatile, I am going to rely on a custom interface:

    public interface IPersonWithEmail
    {
       
string FirstName { get; set; }
       
string LastName { get; set
; }
       
string Email { get; set
; }
    }

 

Now, the attribute itself:

  [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
 
public class AdvancedEmailValidationAttribute : ValidationAttribute

  {
   
public
AdvancedEmailValidationAttribute()
      :
this
(0)
    {
    }
 
   
public AdvancedEmailValidationAttribute(int
maximumLength)
    {
      MaximumLength = maximumLength == 0 ?
        50 : maximumLength;
      ErrorMessage =
string.Format("Email cannot contain first or last name and cannot be longer than {0} characters."
, MaximumLength);
    }
   
public int MaximumLength { get; private set
; }
 
   
protected override ValidationResult IsValid(object value, ValidationContext
validationContext)
    {
     
var objectToValidate = validationContext.ObjectInstance as IPersonWithEmail
;
     
ValidationResult returnValue = ValidationResult
.Success;
 
     
if (objectToValidate != null
)
      {
       
if (value != null
)
        {
         
if
(
            value.ToString().ToUpper().Contains(objectToValidate.LastName.ToUpper()) ||
            value.ToString().ToUpper().Contains(objectToValidate.LastName.ToUpper()) || 
            value.ToString().Length > MaximumLength)
          {
            returnValue =
new ValidationResult
(ErrorMessage);
          }
        }
      }
     
else

      {
        returnValue =
new ValidationResult("You must implement IPersonWithEmail on your object to use this rule");
      }
     
return
returnValue;
    }
 
  }

 

As you can see above, I am have a custom property called MaximumLength that I am populating via constructor.  This promotes attribute reuse.  Then, I am overriding IsValid method.  This method simply checks the rule.  If rule succeeds, it returns ValidationResult.Success.  Otherwise it returns instance of ValidationResult with a specific error message.  That is all.  To use the attribute, I simply decorate the email field with this attribute as below:

    [AdvancedEmailValidation()]
   
public string Email { get; set
; }

 

Now, if I run the sample, I will see this in action.  Because I do not have client rules yet, I will see the postback, but when my screen comes back, the error will be shown.

To make this functionality more interactive, I am now going to add client side validation.  TO start with, I will extend my attribute with client side validation using IClientValidatable interface.  Here is what it looks like:

  [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
 
public class AdvancedEmailValidationAttribute : ValidationAttribute, IClientValidatable

  {
   
public AdvancedEmailValidationAttribute()
      :
this
(0)
    {
    }
 
   
public AdvancedEmailValidationAttribute(int
maximumLength)
    {
      MaximumLength = maximumLength == 0 ?
        50 : maximumLength;
      ErrorMessage =
string.Format("Email cannot contain first or last name and cannot be longer than {0} characters."
, MaximumLength);
    }
   
public int MaximumLength { get; private set
; }
 
   
protected override ValidationResult IsValid(object value, ValidationContext
validationContext)
    {
     
var objectToValidate = validationContext.ObjectInstance as IPersonWithEmail
;
     
ValidationResult returnValue = ValidationResult
.Success;
 
     
if (objectToValidate != null
)
      {
       
if (value != null
)
        {
         
if
(
            value.ToString().ToUpper().Contains(objectToValidate.LastName.ToUpper()) ||
            value.ToString().ToUpper().Contains(objectToValidate.LastName.ToUpper()) || 
            value.ToString().Length > MaximumLength)
          {
            returnValue =
new ValidationResult
(ErrorMessage);
          }
        }
      }
     
else

      {
        returnValue =
new ValidationResult("You must implement IPersonWithEmail on your object to use this rule");
      }
     
return
returnValue;
    }
 
   
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext
context)
    {
     
var rule = new ModelClientValidationRule

      {
        ErrorMessage = ErrorMessage,
        ValidationType =
"advancedemail"
      };
      rule.ValidationParameters.Add(
"maxlength", MaximumLength);
      rule.ValidationParameters.Add(
"firstname", "FirstName"
);
      rule.ValidationParameters.Add(
"lastname", "LastName"
);
     
yield return
rule;
 
    }
  }

 

This interface only has one member – method called GetClientValidaitonRules.  In my case I am only returning one rule.  I can create a custom rule by inheriting from ModelClientValidationRule, but my use case is simple, so I am not doing it.  I am also adding validation parameters (all strings) that I will need on client side.  It is obviously maximum length, and first and last name property names.  I will use all three at the client to compare email to first and last name as well as maximum length.  The next step in the process is to use jQuery  validation and write methods that inject validation as well as enforce it.

Here is my script (I am including entire partial view for clarity)

@if (false)

 
<reference src="../../Scripts/jquery-1.5.1-vsdoc.js" type="text/javascript" />

 
<reference src="../../Scripts/jquery.validate.js" type="text/javascript" />
 
<reference src="../../Scripts/jquery.validate.unobtrusive.js" type="text/javascript" />
}
@model MvcEFCodeFirst.Data.
Attendee
@
using (Html.BeginForm(new { Id = "AttendeeForm" }))
{
  @Html.ValidationSummary(
true
)
 
<fieldset>

   
<legend>Attendee</legend>
   
<div class="editor-label">
      @Html.LabelFor(model => model.FirstName)
   
</div>
   
<div class="editor-field">
      @Html.EditorFor(model => model.FirstName)
      @Html.ValidationMessageFor(model => model.FirstName)
   
</div>
   
<div class="editor-label">
      @Html.LabelFor(model => model.LastName)
   
</div>
   
<div class="editor-field">
      @Html.EditorFor(model => model.LastName)
      @Html.ValidationMessageFor(model => model.LastName)
   
</div>
   
<div class="editor-label">
      @Html.LabelFor(model => model.Email)
   
</div>
   
<div class="editor-field">
      @Html.EditorFor(model => model.Email)
      @Html.ValidationMessageFor(model => model.Email)
   
</div>
   
<div class="editor-label">
      @Html.LabelFor(model => model.Notes)
   
</div>
   
<div class="editor-field">
      @Html.EditorFor(model => model.Notes)
      @Html.ValidationMessageFor(model => model.Notes)
   
</div>
    @
if (Model.AttendeeID > 0)
    { 
      @Html.HiddenFor(model => model.AttendeeID)
    }
 
</fieldset>

}
<script type="text/javascript">
 
 
  (
function ($) {
 
    $.validator.addMethod(
‘advancedemail’, function
(value, element, param) {
     
if (!value) return false
;
     
var lastName = $(‘#’
+ param.lastname).val();
     
var firstName = $(‘#’
+ param.firstname).val();
     
var
maxlength = param.maxlength;
     
if
(value.toString().toLowerCase().indexOf(lastName.toString().toLowerCase()) >= 0 ||
        value.toString().toLowerCase().indexOf(firstName.toString().toLowerCase()) >= 0 ||
          value.toString().length > maxlength) {
       
return false
;
      }
     
return true
;
    });
 
 
    $.validator.unobtrusive.adapters.add(
     
‘advancedemail’
,
      [
'maxlength', 'firstname', 'lastname'
],
     
function
(options) {
 
       
var
params = {
          maxlength: options.params.maxlength,
          firstname: options.params.firstname,
          lastname: options.params.lastname
        };
        
        options.rules[
'advancedemail'
] = params;
       
if
(options.message) {
          options.messages[
'advancedemail'
] = options.message;
        }
 
      });
  } (jQuery));

</script
>

 

As you can see from above, my code to inject the rule consists of two components – function that performs validation (follows validator.addMethod call) and function that injects it into validation infrastructure (validator.unobtrusive.adapters.add call).  First, let me examine the second function that does injection.  I am adding new unobtrusive adapater with the name of advancedemail.  This matches what I put into my attribute – this is how the attribute and client side work together.  I am pumping the parameters into function that will return validation method options as a class called “params”, as well as message.

The actual validation function is interesting as well.  I am getting the values from the form by using jQuery selector for the form input control name that is actually an option passed in by my attribute.  Then I am actaully enforcing the rule by doing basic string manipulation.  ALl I need to do is return true or false from the actual validation function, where false means the rule failed.  I am injecting the entire set of functionality into partial view by including a script tag that executes right away.  If you view source of this page, you will see how my attribute data got injected into the view:

    <div class="editor-label">

      <label for="Email">Email</label>

    </div>

    <div class="editor-field">

      <input class="text-box single-line" data-val="true" data-val-advancedemail="Email cannot contain first or last name and cannot be longer than 50 characters." data-val-advancedemail-firstname="FirstName" data-val-advancedemail-lastname="LastName" data-val-advancedemail-maxlength="50" data-val-length="The field Email must be a string with a maximum length of 250." data-val-length-max="250" data-val-regex="Email is not in a correct format" data-val-regex-pattern="^[A-Za-z0-9](([_\.\-]?[a-zA-Z0-9]+)*)@([A-Za-z0-9]+)(([\.\-]?[a-zA-Z0-9]+)*)\.([A-Za-z]{2,})$" data-val-remote="Email address is duplicate" data-val-remote-additionalfields="*.Email,*.AttendeeID" data-val-remote-url="/MvcEFCodeFirst/Attendee/DuplicateEmail" data-val-required="Email is required" id="Email" name="Email" type="text" value="" />

      <span class="field-validation-valid" data-valmsg-for="Email" data-valmsg-replace="true"></span>

    </div>

I know, a little hard to read, but you can certainly see the result of my attribute by looking at the data that starts with data-val-advancedemail.

One thing to note is that my validator name is all lower case, and this is because jQuery validation may generate the error – method name must be in lower case without digits.

To summarize, client and server side validation should both be covered when it comes to rules.  Server side can be easily enforced with ValidationAttribute.  Client side validation required three moving parts – IClientValidatable on the server side, function that performs validation at the client side and code that creates unobtrusive validation adapter that points to that function.

You can download entire sample here.

Post to Twitter

SSRS Report Viewer Error

I was working on a particular production problem yesterday. Sometimes when a user clicked on print button in SSRS Web Report Viewer control, and error was shown, and report is only partially printed, maybe 2 pages out of 4 are printed. Specific error that is shown to the user stated “An error occurred during printing (0×80004005)”.
Don’t you hate problems that start with “it only breaks sometimes”? Moreover, those that have totally nondescript errors?

One thing I learned a while ago, is that is web farm environment these types of problems are often related to configuration issues on one server vs. the other. So, I took a look at all the servers, and they all had SSRS Report Viewer redistributable installed. What was also interesting, is that preview worked fine, the error only occured when print button is pushed.
It took me a bit to replicate the problem, and then I did what I often do when debugging web problems – I fired up Fiddler. What Fiddler was reporting is that I was getting 404 Not Found error for Reserved.ReportViewerWebControl.axd. I could not understand why because report viewer redistributable should have installed the HTTP handler for me. I checked first production machine, and it was there. So, I checked the rest of the production servers. I found one that was missing the handler. No idea why, the same install was run on all the servers.
So, I added the handler in IIS 7 Management IIS Console -> root server node -> Handler Mapping -> Add Managed Handler with the following entries:
Request Path: Reserved.ReportViewerWebControl.axd
Type:Microsoft.Reporting.WebForms.HttpHandler, Microsoft.ReportViewer.WebForms, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
Name=ReportViewerWebControlHandler
Note: I am using SQL Server 2008 R2, hence the assembly version is 10.0

And voila, the problem went away!
Thanks.

Post to Twitter

Consuming WCF REST Service from WP 7

In this post I will explore a possibility of talking to a WCF REST Service from a Windows Phone 7 device.  This should complete my posts related to consuming and working with data on Windows Phone 7.

I am going to start with creating a WCF REST Service.  First of all, I am going to create data using Entity Framework Code First.  I am going to re-use classes with my previous posts.  I am going to define a handful : Attendee, Session and Session Category.  Here is what Attendee class looks like as it will be the class I will use in my services.

using System.Collections.Generic;
using
System.ComponentModel.DataAnnotations;
 

namespace
VSLiveData.EF
{
   
public class Attendee

    {
        [
Key]
       
public int AttendeeID { get; set
; }
 
        [
StringLength(50), Required
]
       
public string FirstName { get; set
; }
 
        [
StringLength(50), Required
]
       
public string LastName { get; set
; }
 
        [
StringLength(int
.MaxValue)]
       
public string Notes { get; set
; }
 
       
public virtual ICollection<Session> Sessions { get; set
; }
    }
}

 

Nest step is to define a service.  .NET 4 comes with a template for RESTfull WCF Service, and I am going to use it to get a head start on my code.  I am going to right click on my solution, and in Add New Item dialog I will select WCF REST Service Applications.

image

In next step I will rename and update created service.  I am going to rename it to JSONDataService.  I am going to start with a method that get list of attendees sorted by last name:

 

using System.Collections.Generic;
using
System.Linq;
using
System.ServiceModel;
using
System.ServiceModel.Activation;
using
System.ServiceModel.Web;
using
VSLiveData.EF;
 

namespace
WcfRestService
{
    [
ServiceContract
]
    [
AspNetCompatibilityRequirements
(
        RequirementsMode =
AspNetCompatibilityRequirementsMode
.Allowed)]
    [
ServiceBehavior(InstanceContextMode = InstanceContextMode
.PerCall)]
   
public class JSONDataService

    {
 
        [
WebGet(UriTemplate = "/Attendee/List", ResponseFormat = WebMessageFormat.Json)]
       
public List<Attendee
> GetList()
        {
           
using (VSLiveContext context = new VSLiveContext
())
            {
                context.Configuration.LazyLoadingEnabled =
false
;
                context.Configuration.ProxyCreationEnabled =
false
;
               
return
context.Attendees.ToList();
            }
        }

 

A couple of important things to notice here.  I am turning off proxy creation.  I have to do this, otherwise I will get serialization problems.  I am also turning off lazy loading because I do not want to populate navigation properties, plus I will get an exception if I touch that property if my code is outside of using statement.  You will see that I specify uri template as well.  I want to use meaningful path for it.  I also specify JSON format for returned data.  Let’s take a look at create method next

        [WebInvoke(UriTemplate = "/Attendee/Create", Method = "POST"
            ResponseFormat =
WebMessageFormat
.Json, 
            RequestFormat =
WebMessageFormat
.Json)]
       
public Attendee Create(Attendee
attendee)
        {
           
using (VSLiveContext context = new VSLiveContext
())
            {
                context.Attendees.Add(attendee);
                context.SaveChanges();
            }
           
return
attendee;
        }

 

 

The code to actually save attendee is pretty easy – I am utilizing entity framework code first API to add new attendee to the collection, save and return new attendee.  Entity framework will populate ID for me as part of Save method.  I also specify JSON as my format for incoming and outgoing data.  The rest of the methods are very similar, so here is entire class:

using System.Collections.Generic;
using
System.Linq;
using
System.ServiceModel;
using
System.ServiceModel.Activation;
using
System.ServiceModel.Web;
using
VSLiveData.EF;
 

namespace
WcfRestService
{
    [
ServiceContract
]
    [
AspNetCompatibilityRequirements
(
        RequirementsMode =
AspNetCompatibilityRequirementsMode
.Allowed)]
    [
ServiceBehavior(InstanceContextMode = InstanceContextMode
.PerCall)]
   
public class JSONDataService

    {
 
        [
WebGet(UriTemplate = "/Attendee/List", ResponseFormat = WebMessageFormat.Json)]
       
public List<Attendee
> GetList()
        {
           
using (VSLiveContext context = new VSLiveContext
())
            {
                context.Configuration.LazyLoadingEnabled =
false
;
                context.Configuration.ProxyCreationEnabled =
false
;
               
return
context.Attendees.ToList();
            }
        }
 
        [
WebInvoke(UriTemplate = "/Attendee/Create", Method = "POST"

            ResponseFormat =
WebMessageFormat
.Json, 
            RequestFormat =
WebMessageFormat
.Json)]
       
public Attendee Create(Attendee
attendee)
        {
           
using (VSLiveContext context = new VSLiveContext
())
            {
                context.Attendees.Add(attendee);
                context.SaveChanges();
            }
           
return
attendee;
        }
 
        [
WebGet(UriTemplate = "/Attendee/Get/{id}"

            ResponseFormat =
WebMessageFormat
.Json)]
       
public Attendee Get(string
id)
        {
           
Attendee attendee = null
;
           
using (VSLiveContext context = new VSLiveContext
())
            {
                context.Configuration.LazyLoadingEnabled =
false
;
                context.Configuration.ProxyCreationEnabled =
false
;
               
int attendeeID = int
.Parse(id);
                attendee = context.Attendees.Where(one => one.AttendeeID == attendeeID).FirstOrDefault();
            }
           
return
attendee;
        }
 
        [
WebInvoke(UriTemplate = "/Attendee/Update", Method = "PUT"

            ResponseFormat =
WebMessageFormat.Json, RequestFormat = WebMessageFormat
.Json)]
       
public Attendee Update(Attendee
attendee)
        {
           
using (VSLiveContext context = new VSLiveContext
())
            {
                context.Attendees.Attach(attendee);
                context.Entry(attendee).State = System.Data.
EntityState
.Modified;
                context.SaveChanges();
            }
           
return
attendee;
        }
 
        [
WebInvoke(UriTemplate = "/Attendee/Delete/{id}", Method = "DELETE"
)]
       
public void Delete(string
id)
        {
           
using (VSLiveContext context = new VSLiveContext
())
            {
               
var attendee = new Attendee() { AttendeeID = int
.Parse(id) };
                context.Attendees.Attach(attendee);
                context.Entry(attendee).State = System.Data.
EntityState
.Deleted;
                context.SaveChanges();
            }
        }
 
    }
}

 

I have to register routes for my service in Global.asax.cs file:

using System;
using
System.ServiceModel.Activation;
using
System.Web;
using
System.Web.Routing;
 

namespace
WcfRestService
{
   
public class Global : HttpApplication

    {
       
void Application_Start(object sender, EventArgs e)
        {
            RegisterRoutes();
        }
 
       
private void
RegisterRoutes()
        {
           
RouteTable.Routes.Add(new ServiceRoute("JSONDataService", new WebServiceHostFactory(), typeof(JSONDataService
)));
        }
    }
}

 

In my web.config I just need to set my connection string for my data context and specify routing engine

 

<?xml version="1.0"?>
<configuration>
 
           <connectionStrings>
                      <add
                        name="VSLive"
                        connectionString="Server=.;Database=VSLive;Trusted_Connection=True;
"
                        providerName="System.Data.SqlClient"/>

           </connectionStrings>
 
           <system.web>
                      <compilation debug="true" targetFramework="4.0" />
           </system.web>
 
           <system.webServer>
                      <modules runAllManagedModulesForAllRequests="true">
                                 <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web, Version=4.0.0.0,

Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
                      </modules>
           </system.webServer>
 
           <system.serviceModel>
                      <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
                      <standardEndpoints>
                                 <webHttpEndpoint>
                                            <standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true"/>
                                 </webHttpEndpoint>
                      </standardEndpoints>
           </system.serviceModel>

 

 

Now, it is time to get to windows phone 7 app.  Just add new project and select Windows Phone 7 application.  The most interesting part is my view model that talks to my WCF service.  First of all, I am going to add a property to hold collection of attendees:

        public ObservableCollection<Attendee> Items { get; private set; }

 

Next, I am going to use WebClient to get the data.  I could also use HTTPRequest.  The difference between the two is that callbacks from WebClient are automatically marshaled to UI thread.  Here is how I would get the list of attendees:

        /// <summary>
       
/// Creates and adds a few ItemViewModel objects into the Items collection.
       
/// </summary>
       
public void LoadData()
        {
           
WebClient client = new WebClient
();
            client.OpenReadCompleted +=
new OpenReadCompletedEventHandler
(client_OpenReadCompleted);
            client.OpenReadAsync(
new Uri(@"http://localhost/WcfRestService/JSONDataService/Attendee/List"
));
 
   

        }
 
       
void client_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
        {
           
ObservableCollection<Attendee> data = new ObservableCollection<Attendee
>();
           
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(List<Attendee
>));
           
List<Attendee> attendees = (List<Attendee
>)serializer.ReadObject(e.Result);
            attendees.ForEach(one => Items.Add(one));
 

        }

 

Let me explain what this code does.  I am creating a web client, then I am subscribing to completed event, then I am calling OpenRead.  Because of the URL I am using, this call will eventually end up in the method that matches my URL based on UriTemplate attribute for the method:

        [WebGet(UriTemplate = "/Attendee/List", ResponseFormat = WebMessageFormat.Json)]
       
public List<Attendee
> GetList()
        {
           
using (VSLiveContext context = new VSLiveContext
())
            {
                context.Configuration.LazyLoadingEnabled =
false
;
                context.Configuration.ProxyCreationEnabled =
false
;
               
return
context.Attendees.ToList();
            }
        }

 

In completed handler for read, I am using DataContractJsonSerializer to de-serialize downloaded data into List of attendees.  Then I am adding them to the items collection, which in turn is exposed to UI as following:

                <ListBox x:Name="FirstListBox" Margin="0,0,-12,0" ItemsSource="{Binding Items}" >
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <StackPanel Margin="0,0,0,17" Width="432" Height="78">
                                <TextBlock Text="{Binding FirstName}" TextWrapping="Wrap" 
                                         
Style="{StaticResource PhoneTextExtraLargeStyle}"/>

                                <TextBlock Text="{Binding LastName}" TextWrapping="Wrap" 
                                         
Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>

                            </StackPanel>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>

 

Next, Let’s look at the Create (Insert) method, as it demonstrates how to post data to the service.

        public void OnSaveAttendee(object parameter)
        {
           
string json = null
;
           
WebClient client = new WebClient
();
            client.Headers[
"Content-Type"] = "application/json"
;
 
           
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(Attendee
));
           
using (MemoryStream stream = new MemoryStream
())
            {
                serializer.WriteObject(stream, CurrentAttendee);
                stream.Flush();
                json =
Encoding.UTF8.GetString(stream.ToArray(), 0, (int
)stream.Length);
 
            }
            client.UploadStringCompleted +=
new UploadStringCompletedEventHandler
(client_UploadStringCompleted);
            client.UploadStringAsync(
new Uri("http://localhost/WcfRestService/JSONDataService/Attendee/Create"), "POST"
, json);
        }
 
       
void client_UploadStringCompleted(object sender, UploadStringCompletedEventArgs
e)
        {
           
if (e.Error == null
)
            {
               
MessageBox.Show("OK"
);
            }
           
else

            {
               
MessageBox
.Show(e.Error.Message);
            }
 
        }

 

Now, I am reversing the order of operations.  I am serializing Attendee instance to Json, then using UTF8 encoding to convert the data to a string.  One important part to remember is to set content type on the request to JSON, otherwise you will get 404 Not Found.  In completed handler I am just checking for errors.  Again, I will end up eventually in my service’s Create method based on URI Template.

You can download entire solution here.  You will also notice that even though my classes on the client, such as Attendee:

using System.Collections.Generic;
using
System.ComponentModel;
 

namespace
VSLiveData.EF
{
   
public class Attendee : INotifyPropertyChanged

    {
       
public int AttendeeID { get; set; }
 
       
public string FirstName { get; set
; }
 
       
public string LastName { get; set
; }
 
       
public string Notes { get; set
; }
 
       
public virtual ICollection<Session> Sessions { get; set
; }
 
       
public event PropertyChangedEventHandler
PropertyChanged;
 
       
private void NotifyPropertyChanged(string
propertyName)
        {
           
PropertyChangedEventHandler
handler = PropertyChanged;
           
if (null
!= handler)
            {
                handler(
this, new PropertyChangedEventArgs
(propertyName));
            }
        }
    }
}

 

I am not calling NotifyPropertyChanged anywhere.  This is because I am using NotifyPropertyChangedWeaver, which is awesome!

Thanks.

Post to Twitter

ASP.NET MVC Custom Authentication

The other day I was working on a sample application and was trying to come up with an efficient way to handle authentication and authorization.  I decided to consolidate this code by implementing custom principal and identity objects.  I find this approach very flexible and concise.  I wanted to document it for my own benefit and to gather some feedback if anyone is willing to share.

First of all, I am going to setup a brand new MVC project.  I will pick internet template to get me a head start on creating basic authentication database and classes.  Next I will run the application one time and register a user.  Next, I am going to select Project->ASP.NET Configuration. I am going to enable roles, create a few and assign them to my user.  Now my preparation work is done and it is rime to write some classes.  If you ever looked at the interfaces IIdentity and IPrincipal, you probably already know what I am going to write, but the trick is that I am going to use membership provider to do authentication and roles provider to do authorization.

First of all, I am going to create some simple interfaces for both classes for general cleanliness and ability to mock both classes for tests:

using System.Security.Principal;
 

namespace
MvcFormsAuth.Security
{
   
public interface ICustomIdentity : IIdentity

    {
       
bool IsInRole(string role);
       
string
ToJson();
    }
}

using System.Security.Principal;
 

namespace
MvcFormsAuth.Security
{
   
public interface ICustomPrincipal : IPrincipal

    {
 
    }
}

 

This part was simple.  Now, the actual implementation.  To authenticate I am going to use membership provider, but you can just as easily plug in custom implementation.

        /// <summary>
       
/// Authenticate and get identity out with roles
       
/// </summary>
       
/// <param name="userName">User name</param>
       
/// <param name="password">Password</param>
       
/// <returns>Instance of identity</returns>
       
public static CustomIdentity GetCustomIdentity(string userName, string password)
        {
           
CustomIdentity identity = new CustomIdentity
();
           
if (Membership
.ValidateUser(userName, password))
            {
                identity.IsAuthenticated =
true
;
                identity.Name = userName;
               
var roles = System.Web.Security.Roles
.GetRolesForUser(userName);
                identity.Roles = roles;
               
return
identity;
            }
           
return
identity;
        }

 

As you can see, I am creating an instance of the object, but only setting the properties if membership provider confirms identity.  I am also getting a list of roles and saving it off with identity.  Of course, you can add some custom properties to it as well.  My next step is come up with scheme to save this information in a cookie, thus being able to add custom information to the authentication cooking.  To do so, I am going to use json based serialization.  I am also going to create a custom class to pump my information into such as :

using System;
 

namespace
MvcFormsAuth.Security
{
   
/// <summary>

   
/// Private members have short names to preserve space using json serialization
   
/// </summary>
   
public class IdentityRepresentation
    {
       
private bool ia;
 
       
public bool
IsAuthenticated
        {
           
get { return
ia; }
           
set { ia = value
; }
        }
 
       
private string
n;
 
       
public string
Name
        {
           
get { return
n; }
           
set { n = value
; }
        }
 
       
private string
r;
 
       
public string
Roles
        {
           
get { return
r; }
           
set { r = value
; }
        }
        
    }
}

 

You noticed that field names are very short.  I am doing this to save space during serialization process.  There is a limit to how much information can be stored in a cookie, and every byte matters in this case.  Here is what my serialization code looks like:

        /// <summary>
       
/// Create serialized string for storing in a cookie
       
/// </summary>
       
/// <returns>String representation of identity</returns>
       
public string ToJson()
        {
           
string returnValue = string
.Empty;
           
IdentityRepresentation representation = new IdentityRepresentation
()
            {
                IsAuthenticated =
this
.IsAuthenticated,
                Name =
this
.Name,
                Roles =
string.Join("|", this
.Roles)
            };
           
DataContractJsonSerializer
jsonSerializer = 
               
new DataContractJsonSerializer(typeof(IdentityRepresentation
));
           
using (MemoryStream stream = new MemoryStream
())
            {
                jsonSerializer.WriteObject(stream, representation);
                stream.Flush();
               
byte
[] json = stream.ToArray();
                returnValue =
Encoding
.UTF8.GetString(json, 0, json.Length);
            }
 
           
return
returnValue;
        }

 

My complete identity class follows:

using System;
using
System.IO;
using
System.Linq;
using
System.Runtime.Serialization.Json;
using
System.Text;
using
System.Web.Security;
 

namespace
MvcFormsAuth.Security
{
   
public class CustomIdentity : ICustomIdentity

    {
       
/// <summary>
       
/// Authenticate and get identity out with roles
       
/// </summary>
       
/// <param name="userName">User name</param>
       
/// <param name="password">Password</param>
       
/// <returns>Instance of identity</returns>
       
public static CustomIdentity GetCustomIdentity(string userName, string password)
        {
           
CustomIdentity identity = new CustomIdentity
();
           
if (Membership
.ValidateUser(userName, password))
            {
                identity.IsAuthenticated =
true
;
                identity.Name = userName;
               
var roles = System.Web.Security.Roles
.GetRolesForUser(userName);
                identity.Roles = roles;
               
return
identity;
            }
           
return
identity;
        }
 
       
private
CustomIdentity() { }
 
       
public string
AuthenticationType
        {
           
get { return "Custom"
; }
        }
 
       
public bool IsAuthenticated { get; private set
; }
 
       
public string Name { get; private set
; }
 
       
private string[] Roles { get; set
; }
 
       
public bool IsInRole(string
role)
        {
           
if (string
.IsNullOrEmpty(role))
            {
               
throw new ArgumentException("Role is null"
);
            }
           
return
Roles.Where(one => one.ToUpper().Trim() == role.ToUpper().Trim()).Any();
        }
 
       
/// <summary>

       
/// Create serialized string for storing in a cookie
       
/// </summary>
       
/// <returns>String representation of identity</returns>
       
public string ToJson()
        {
           
string returnValue = string
.Empty;
           
IdentityRepresentation representation = new IdentityRepresentation
()
            {
                IsAuthenticated =
this
.IsAuthenticated,
                Name =
this
.Name,
                Roles =
string.Join("|", this
.Roles)
            };
           
DataContractJsonSerializer
jsonSerializer = 
               
new DataContractJsonSerializer(typeof(IdentityRepresentation
));
           
using (MemoryStream stream = new MemoryStream
())
            {
                jsonSerializer.WriteObject(stream, representation);
                stream.Flush();
               
byte
[] json = stream.ToArray();
                returnValue =
Encoding
.UTF8.GetString(json, 0, json.Length);
            }
 
           
return
returnValue;
        }
 
       
/// <summary>

       
/// Create identity from a cookie data
       
/// </summary>
       
/// <param name="cookieString">String stored in cookie, created via ToJson method</param>
       
/// <returns>Instance of identity</returns>
       
public static ICustomIdentity FromJson(string cookieString)
        {
 
           
IdentityRepresentation serializedIdentity = null
;
           
using (MemoryStream stream = new MemoryStream(Encoding
.UTF8.GetBytes(cookieString)))
            {
               
DataContractJsonSerializer
jsonSerializer = 
                   
new DataContractJsonSerializer(typeof(IdentityRepresentation
));
                serializedIdentity = jsonSerializer.ReadObject(stream)
as IdentityRepresentation
;
            }
           
CustomIdentity identity = new CustomIdentity
()
            {
                IsAuthenticated = serializedIdentity.IsAuthenticated,
                Name = serializedIdentity.Name,
                Roles = serializedIdentity.Roles
                    .Split(
new string[] { "|" }, StringSplitOptions
.RemoveEmptyEntries)
            };
           
return
identity;
        }
 
    }
}

 

Principal class is much lighter, and it mostly responsible for setting User property on HttpContext:

using System;
using
System.Security.Principal;
using
System.Web;
using
System.Web.Security;
 

namespace
MvcFormsAuth.Security
{
   
public class CustomPrincipal : ICustomPrincipal

    {
       
private CustomPrincipal() { }
 
       
private CustomPrincipal(ICustomIdentity
identity) 
        {
           
this
.Identity = identity;
        }
 
       
public IIdentity Identity { get; private set
; }
 
       
public bool IsInRole(string
role)
        {
           
if (string
.IsNullOrEmpty(role))
            {
               
throw new ArgumentException("Role is null"
);
            }
           
return ((ICustomIdentity
)Identity).IsInRole(role);
        }
 
 
       
public static void
Logout()
        {
           
HttpContext
.Current.User = 
               
new GenericPrincipal(new GenericIdentity(""), new string
[] { });
        }
 
       
/// <summary>

       
/// Login
       
/// </summary>
       
/// <param name="userName">User name</param>
       
/// <param name="password">Password</param>
       
/// <param name="rememberMe">True, if authentication should persist between browser sessions
       
/// </param>
       
/// <returns>True if login succeeds</returns>
       
public static bool Login(string userName, string password, bool rememberMe)
        {
           
var identity = CustomIdentity
.GetCustomIdentity(userName, password);
           
if
(identity.IsAuthenticated)
            {
               
HttpContext.Current.User = new CustomPrincipal
(identity);
               
FormsAuthenticationTicket
ticket =
                      
new FormsAuthenticationTicket
(
                           1, identity.Name,
DateTime.Now, DateTime
.Now.AddMinutes(30), rememberMe,
                           identity.ToJson(),
FormsAuthentication
.FormsCookiePath);
               
string encryptedTicket = FormsAuthentication
.Encrypt(ticket);
 
               
var cookie = new HttpCookie(FormsAuthentication
.FormsCookieName, encryptedTicket);
                cookie.Path =
FormsAuthentication
.FormsCookiePath;
               
if
(rememberMe)
                {
                    cookie.Expires =
DateTime.Now.AddYears(1);// good for one year

                }
 
               
HttpContext.Current.Response.Cookies.Add(cookie);
            }
           
return
identity.IsAuthenticated;
        }
 
       
public static bool Login(string
cookieString)
        {
           
ICustomIdentity identity = CustomIdentity
.FromJson(cookieString);
           
if
(identity.IsAuthenticated)
            {
               
HttpContext.Current.User = new CustomPrincipal
(identity);
            }
           
return
identity.IsAuthenticated;
        }
    }
}

 

The most interested code is in Login methods.  Primary login method delegates authentication to identity class, then just sets User on HttpContext.  You may notice how “remember me” is implemented.  I am doing it by setting expiration date on authentication cookie.  I am making it valid for one year since login.

So far so good.  Now what do we do when authenticated user hits a page?  We will manually implement sliding expiration and call the secondary login method of out principal.  The most logical place for that is in a base controller we are going to create by overriding OnAuthorization method:

using System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Web;
using
System.Web.Mvc;
using
System.Web.Security;
using
MvcFormsAuth.Security;
 

namespace
MvcFormsAuth.Controllers
{
    [
Authorize
]
   
public class AuthorizedController : Controller

    {
       
protected override void OnAuthorization(AuthorizationContext filterContext)
        {
           
base
.OnAuthorization(filterContext);
           
HttpCookie cookie = Request.Cookies[FormsAuthentication
.FormsCookieName];
           
if (cookie != null
)
            {
               
FormsAuthenticationTicket ticket = FormsAuthentication
.Decrypt(cookie.Value);
               
var newTicket = FormsAuthentication
.RenewTicketIfOld(ticket);
               
if
(newTicket.Expiration != ticket.Expiration)
                {
                   
string encryptedTicket = FormsAuthentication
.Encrypt(newTicket);
 
                    cookie =
new HttpCookie(FormsAuthentication
.FormsCookieName, encryptedTicket);
                    cookie.Path =
FormsAuthentication
.FormsCookiePath;
                    Response.Cookies.Add(cookie);
                }
               
CustomPrincipal
.Login(ticket.UserData);
            }
        }
    }
}

 

Now all my controllers that need to be authenticated and authorized can just inherit from this base class.  The login call simply uses user data I added to start with to rehydrate the identity and principal objects.

To summarizer, because I am saving some necessary data in the cooking I am saving an extra call or two to the database to get user and roles information on subsequent requests.

Here is a little bit more information on the subject that will be helpful

To enforce authentication rules on your entire site, add the following to web.config

           <system.web>

 
                      <authentication mode="Forms">
                                 <forms loginUrl="~/Account/LogOn" timeout="2880" />
                      </authentication>
 
                      <authorization>
                                 <deny users="?"/>
                      </authorization>

 

Make sure to exclude your styles and scripts from authentication.  Otherwise you will notice that your login page is not styled.  To do so, just add location configuration to your web.config as follows.  The same applies to your login/register, etc… methods.

           <!– allow unauthenticated users to get CSS data –>
           <location path="Content">
                      <system.web>
                                 <authorization>
                                            <allow users="?"/>
                                 </authorization>
                      </system.web>
           </location>
           <location path="Account">
                      <system.web>
                                 <authorization>
                                            <allow users="?"/>
                                 </authorization>
                      </system.web>
           </location>
</configuration>

 

 

You can download entire sample application here.

Please share your opinions on this subject.

Post to Twitter

ReMIX South is at August 6th in Atlanta

 

August 6th marks the 20th anniversary of the World Wide Web. Coincidentally, it is also the day of the Second Annual ReMIX Conference in Atlanta, Georgia.

The past year has seen many changes in Microsoft strategy as well as new innovations in web and mobile development outside of Microsoft. ReMIX will catch you up on those changes and prepare you for the next year of development and design trends.

In the spirit of bringing developers and designers together, organizers are proud to announce Albert Shum as our keynote speaker. Albert Shum is the General Manager of the Windows Phone Design Studio, the team that formulated the Metro Design Language used on Windows Phone and Windows 8.

There are four tracks this year: User Experience, Web, Mobile & Tablet, and Kinect. Our handpicked speakers come from both the Microsoft community and beyond it. Please register as early as possible at http://remixsouth.eventbrite.com/ so that organizers can make proper accommodations for all attendees.

The UX Track will cover design practices for an increasingly complex world that includes websites, interactive, mobile, tablets and traditional desktop apps. Speakers include James Chittenden (UX Architect at Microsoft), Rick Barraza (Principal UX Architect at Cynergy), Matthias Shapiro (Veracity), and Zach Pousman (Director of Strategy at IQ Interactive), and Jenn Downs (Design Researcher at MailChimp).

The Web Track is made up of web experts from outside the usual Microsoft fold. They will walk you through the HTML5 buzz and the core technologies that make it work: CSS3 and JQuery. J. Cornelius, VP Operations at CoffeeCup Software, will talk on HTML5. Josh Netherton of Mailchimp will talk on “CSS3: More Than Just Rounded Corners.” John Agan of Epic Labs will walk us through our paces with JQuery. Mark Barilla of Home Depot will introduce us to HTML5 Design Principles, while Theo Rasendorf of Matador will school us in “Type 101”.

In the Mobile & Tablet Track, Shawn Wildermuth (Agilitrain), Rob Cameron (Microsoft), Luke Hamilton (Creative Director, Razorfish) and Jeremy Likness (Wintellect) will teach us about phone game development, design best-practices for multitouch, the new Windows Phone Mango release, Silverlight Development for Tablets and Windows 8.

Finally, in the Kinect Track we will celebrate Microsoft’s surprise hit of the year by bringing together some top players from the Kinect Hacking world for a day of talks, teach-ins and expert panels. Speakers and panelists include Zahoor Zafrulla of Georgia Tech, Steve Dawson of Razorfish Emerging Experiences, Rick Barraza of Cynergy and Josh Blake of InfoStrat, the founder of the OpenKinect forums and co-founder of the OpenNI forums.

Additionally, Microsoft will be providing all-day labs on Windows Phone development while our Commons room will be set up for impromptu conversations, hands-on opportunities with new technologies and general networking with businesses, new friends and old friends.

Post to Twitter

SQL CE in Mango–Updating the Schema

In my previous post I talked about general usage of SQL CE database in Mango.  In this example I am going to talk about keeping the database schema updated.

For example, I want to add a column to Person table from previous post.  I would like to add Notes column with the following definition:

        [Column(DbType = "NVarChar(300) NULL")]

        public string Notes { get; set; }

 

Now I am going to use DatabaseSchemaUpdater class to accomplish this.  First of all, I have to add using statement to my program in order to invoke extension method on my data context:

using Microsoft.Phone.Data.Linq;

 

Now, I am going to add some code after the database exists check and add the column as follows:

                DatabaseSchemaUpdater db = App.CurrentApp.DB.CreateDatabaseSchemaUpdater();

                if (db.DatabaseSchemaVersion == 0)

                {

                    db.AddColumn<Person>("Notes");

                    db.DatabaseSchemaVersion = 1;

                    db.Execute();

                }

 

Here is what I am doing here.  I am checking for DB version, which I am going to assume responsibility for updating from now on.  I am adding notes column called Notes to Person table.  Then I am bumping version number for subsequent updates.  Lastly, I am firing Execute method to commit my changes.  Pretty easy all-and-all.  I only wish that Entity Framework code first had similar functionality.

Post to Twitter

SQL CE on Windows Phone 7.1 (Mango)

In the past I have written about dealing with data on Windows Phone 7, including WCF Services, WCF Data Services and Isolated Storage.  One thing that was missing in the initial release is native RDBMS, such as SQL CE.  Luckily, Mango update that should be released later this year finally exposes SQL CE to developers.

Even I admit that Isolated Storage DB was a useful tool for me in absence if SQL CE.  That is why I wrote my project on CodePlex.  Having said that, I would likely not take on this task if SQL CE was available in Windows Phone 7.  As a good little developer, I wanted to spend some time and educate myself on how to use SQL CE in Mango.  This post describes my adventures on the subject.

First of all, you have download and install Mango (7.1) update.  Current update version is beta 2.  You can download it here.

Now, let’s create new project and select 7.1 as target framework.  Now, let’s get acquainted with Linq to SQL API for Windows Phone 7.  Yes, interestingly enough ORM framework that is available on the phone is L2S not Entity Framework.  I will not be commenting on this subject, let’s just look at what is available.

We are using code only approach with L2S, so we are going to define some tables in code.  I want to document some relationships, so I will use the following logical structure: Person with a Title and a number of Interests.  Let’s look at the simplest table – PersonTitle.

using System.Data.Linq.Mapping;

 

namespace MangoDataApp

{

    [Table]

    public class PersonTitle

    {

        [Column(DbType = "INT NOT NULL IDENTITY", IsDbGenerated = true,

            IsPrimaryKey = true, AutoSync = AutoSync.OnInsert)]

        public int PersonTitleID { get; set; }

 

        [Column(DbType = "NVarChar(30) NOT NULL")]

        public string Title { get; set; }

    }

}

 

Let’s look at the code in details.  You will notice that I use a couple of attributes to designate this class as Table and define columns.  I find Table attribute pretty easy.  Column attribute is a lot more annoying because I have to remember the column definition and type it as a magic string.  I do not like this, but what can one do?  I designate my primary key as Identity column and force to sync up the newly generated ID after the insert is committed.  So far so good.  Now I am going to take a closer look at defining an one-to-many relationship.  I will use Person with a Title for this.  Here is what my Person class looks like:

    [Table]

    public class Person

    {

        [Column(DbType = "INT NOT NULL IDENTITY", IsDbGenerated = true,

            IsPrimaryKey = true, AutoSync = AutoSync.OnInsert)]

        public int PersonID { get; set; }

 

        [Column(DbType = "NVarChar(30) NOT NULL")]

        public string FirstName { get; set; }

 

        [Column(DbType = "NVarChar(50) NOT NULL")]

        public string LastName { get; set; }

 

        [Column()]

        public int PersonTitleID { get; set; }

 

        private EntityRef<PersonTitle> personTitle;

        [Association(ThisKey = "PersonTitleID", OtherKey = "PersonTitleID",

            Storage = "personTitle")]

        public PersonTitle PersonTitle

        {

            get { return personTitle.Entity; }

            set { personTitle.Entity = value; }

        }

 

 

As you can see above, unlike simple API of Entity Framework Code First I have to jump through a few hoops.  One thing is that I have to create an explicit backing field of type EntityRef.  I am hinting L2S to use this backing field by using Storage parameter of the column attribute.  I also specify keys in both Person and PersonTitle tables.  All-in-all not so bad.  Now let’s look at many-to-many relationship between Person and Person interests.  In this case I have to actually create a class corresponding to my junction table (unlike Entity Framework where I do not need to do this).  Here is my junction table:

using System.Data.Linq;

using System.Data.Linq.Mapping;

 

namespace MangoDataApp

{

    [Table]

    public class PersonInterest

    {

        [Column(IsPrimaryKey = true)]

        public int PersonID { get; set; }

 

        [Column(IsPrimaryKey = true)]

        public int InterestID { get; set; }

 

        private EntityRef<Interest> interest;

        [Association(ThisKey = "InterestID", OtherKey = "InterestID", Storage = "interest")]

        public Interest Interest { get { return interest.Entity; } set { interest.Entity = value; } }

 

        private EntityRef<Person> person;

        [Association(ThisKey = "PersonID", OtherKey = "PersonID", Storage = "person")]

        public Person Person { get { return person.Entity; } set { person.Entity = value; } }

    }

}

 

Again, I am using EntityRef class just like in example above.  Now, how does my Person table take use of that?

using System.Data.Linq;

using System.Data.Linq.Mapping;

 

namespace MangoDataApp

{

    [Table]

    public class Person

    {

        [Column(DbType = "INT NOT NULL IDENTITY", IsDbGenerated = true,

            IsPrimaryKey = true, AutoSync = AutoSync.OnInsert)]

        public int PersonID { get; set; }

 

        [Column(DbType = "NVarChar(30) NOT NULL")]

        public string FirstName { get; set; }

 

        [Column(DbType = "NVarChar(50) NOT NULL")]

        public string LastName { get; set; }

 

        [Association(ThisKey = "PersonID", OtherKey = "PersonID")]

        public EntitySet<PersonInterest> PersonInterests { get; set; }

 

        [Column()]

        public int PersonTitleID { get; set; }

 

        private EntityRef<PersonTitle> personTitle;

        [Association(ThisKey = "PersonTitleID", OtherKey = "PersonTitleID",

            Storage = "personTitle")]

        public PersonTitle PersonTitle

        {

            get { return personTitle.Entity; }

            set { personTitle.Entity = value; }

        }

 

        public Person()

        {

            PersonInterests = new EntitySet<PersonInterest>();

        }

    }

}

 

Pretty easy again – I define Person Interest property as EntitySet this time, not EntityRef.

Let’s take a look at our context.  This class is very simple.  Please notice that I use fields, not properties for tables.  If you use properties you will get an ugly non-descriptive exception.

using System.Data.Linq;

 

namespace MangoDataApp

{

    public class PersonContext : DataContext

    {

        public  PersonContext()

            : base("isostore:/PersonDB.sdf")

        {

 

        }

        public Table<Person> People;

        public Table<Interest> Interests;

        public Table<PersonInterest> PersonInterests;

        public Table<PersonTitle> PersonTitles;

    }

}

 

And that is all there is to it.  Now, let me see how I can pump some data into my database.  Frist of, I am going to expose my database through property of my application class:

    public partial class App : Application

    {

        private static App app;

 

        public static App CurrentApp

        {

            get { return app; }

        }

 

 

        public PersonContext DB { get; private set; }

 

        /// <summary>

        /// Constructor for the Application object.

        /// </summary>

        public App()

        {

            app = this;

            DB = new PersonContext();

 

I have a static property to make the code that uses DB easier:

            if (!App.CurrentApp.DB.DatabaseExists())

            {

                App.CurrentApp.DB.CreateDatabase();

 

Cool.  Now, let’s pump some data into my four tables:

                var int1 = new Interest() { InterestName = "Phone" };

                App.CurrentApp.DB.Interests.InsertOnSubmit(int1);

 

                var int2 = new Interest() { InterestName = "Desktop" };

                App.CurrentApp.DB.Interests.InsertOnSubmit(int2);

 

                var title = new PersonTitle() { Title = "Mr." };

                App.CurrentApp.DB.PersonTitles

                    .InsertAllOnSubmit(new[] { title, new PersonTitle() { Title = "Mrs." } });

 

                App.CurrentApp.DB.SubmitChanges();

 

                var person = new Person() { FirstName = "Sergey", LastName = "Barskiy" };

                person.PersonTitleID = title.PersonTitleID;

 

 

                App.CurrentApp.DB.People.InsertOnSubmit(person);

                App.CurrentApp.DB.SubmitChanges();

 

                PersonInterest pi1 = new PersonInterest()

{ InterestID = int1.InterestID, PersonID = person.PersonID };

                App.CurrentApp.DB.PersonInterests.InsertOnSubmit(pi1);

 

                PersonInterest pi2 = new PersonInterest()

{ InterestID = int2.InterestID, PersonID = person.PersonID };

                App.CurrentApp.DB.PersonInterests.InsertOnSubmit(pi2);

 

                person.PersonInterests.Add(pi1);

                person.PersonInterests.Add(pi2);

                App.CurrentApp.DB.SubmitChanges();

 

The last thing I would like to talk about is lazy / eager loading.  By default L2S will use lazy loading, meaning that your related properties are not retrieved until they are accessed.  Most of that time this is good, but what if I always want to load the title when I get the data?  I just use data load options object to achieve that.

                DataLoadOptions options = new DataLoadOptions();

                options.LoadWith<Person>(c => c.PersonTitle);

                App.CurrentApp.DB.LoadOptions = options;

                var people = App.CurrentApp.DB.People.ToList();

 

You can download sample project here.

Here are some useful links on MSDN:

Column attribute

Linq to SQL Overview

SQL CE Overview for Windows Phone 7.1

SQL CE Connection Strings for the Phone

Post to Twitter

Entity Framework June CTP

Entity Framework CTP was just released.  It contains a large number of new features, including enumerations support and spatial types.  There are also important optimization improvements, such as automatically compiled queries and SQL generation improvements.  You can read more details here.

Enjoy.

Post to Twitter

Atlanta Code Camp

Atlanta Code Camp 2011 took place yesterday, Saturday, June 25 2011. I was one of the organizers of the event.  The event was a success based on some preliminary feedback we gathered during the vent itself.  We have over 250 people attending 54 different sessions.

I did one talk – Using Code First (Code Only) approach with Entity Framework

Since I would like to share my slides and sample code, you can download the zip file by clicking on the title above.

Thank you.

Post to Twitter

Correcting Sorting Issues in Entity Framework Repository

I posted earlier on how to implement repository pattern using Entity Framework Code First, while removing a dependency on IQueryable interface.  I identified an issue that still existed in that code related to sorting.  Sorting is a tricky part because SortBy method on IQueryable needs to have two generic parameters: item type and property that the query is being sorted on.  I could not come up in that version of a generic way to do so.

I am posting a solution to the problem.  I have added new interface I am going to use for sorting:

using System;

using System.Linq;

 

namespace EFCodeFirstExtensions

{

  public interface IOrderByClause<T>

   where T : class, new()

  {

    IOrderedQueryable<T> ApplySort(IQueryable<T> query, bool firstSort);

  }

}

 

The reason I have second parameter to Apply method is that I have to use OrderBy or ThenOrderBy methods depending on where or not I already sorted a query once.  I am also moving the actual sort implementation to the method in order to support a simple implementation in the code that uses repository.  Here is my SortBy classes that implements interface above:

using System;

using System.Linq.Expressions;

using System.Reflection;

using System.Linq;

 

namespace EFCodeFirstExtensions

{

  public class OrderByClause<T, TProperty> : EFCodeFirstExtensions.IOrderByClause<T>

    where T : class, new()

  {

    private OrderByClause()

    {

 

    }

 

    public OrderByClause(

      Expression<Func<T, TProperty>> orderBy,

      SortDirection sortDirection = SortDirection.Ascending)

    {

      OrderBy = orderBy;

      SortDirection = sortDirection;

    }

 

    /// <summary>

    /// Order by expression

    /// </summary>

    private Expression<Func<T, TProperty>> OrderBy { get; set; }

 

    /// <summary>

    /// Sort direction

    /// </summary>

    private SortDirection SortDirection { get; set; }

 

    public IOrderedQueryable<T> ApplySort(IQueryable<T> query, bool firstSort)

    {

      if (SortDirection == EFCodeFirstExtensions.SortDirection.Ascending)

      {

        if (firstSort)

        {

          return query.OrderBy(OrderBy);

        }

        else

        {

          return ((IOrderedQueryable<T>)query).ThenBy(OrderBy);

        }

      }

      else

      {

        if (firstSort)

        {

          return query.OrderByDescending(OrderBy);

        }

        else

        {

          return ((IOrderedQueryable<T>)query).ThenByDescending(OrderBy);

        }

      }

 

    }

 

  }

}

 

As you can see above, my SortBy class is now responsible for applying the sort.  Now I just have to update my repository class to delegate to SortyBy:

    /// <summary>

    /// Select data from database using a where clause

    /// </summary>

    /// <typeparam name="TItem">Type of data to select</typeparam>

    /// <param name="whereClause">Where clause / function</param>

    /// <param name="orderBy">Order by clause</param>

    /// <param name="skip">Paging implementation = number of records to skip</param>

    /// <param name="top">Paging implementation = number of records to return</param>

    /// <param name="include">Navigation properties to include</param>

    /// <returns>Items selected</returns>

    public IEnumerable<TItem> Select<TItem>(

      Expression<Func<TItem, bool>> whereClause = null,

      IOrderByClause<TItem>[] orderBy = null,

      int skip = 0,

      int top = 0,

      string[] include = null)

       where TItem : class, new()

    {

 

      IQueryable<TItem> data = context.Set<TItem>();

      // handle where

      if (whereClause != null)

      {

        data = data.Where(whereClause);

      }

 

      //handle order by

      if (orderBy != null)

      {

        bool isFirstSort = true;

        orderBy.ToList().ForEach(one =>

        {

          data = one.ApplySort(data, isFirstSort);

          isFirstSort = false;

        });

      }

 

      // handle paging

      if (skip > 0)

      {

        data = data.Skip(skip);

      }

      if (top > 0)

      {

        data = data.Take(top);

      }

 

      //handle includes

      if (include != null)

      {

        include.ToList().ForEach(one => data = data.Include(one));

      }

 

      foreach (var item in data)

      {

        yield return item;

      }

    }

 

The code is very simple.  I just have to keep track of whether or not I am on the first sort by clause or not.

Here is the program that uses this method:

      using (var repo = new TestRepo())

      {

        var locs = repo.Select<Location>(one => one.LocationID == 2, new IOrderByClause<Location>[] {

          new OrderByClause<Location, int>(one=>one.LocationID, SortDirection.Descending),

          new OrderByClause<Location, string>(one=>one.LocationName, SortDirection.Ascending)}, 1, 1, new[] { "Attendees" });

 

 

        var thing = locs.ToList();

 

      }

 

As you can see, now I am not relying on IQueryable, yet I am supporting all major functions of queries against database, such as filtering, sorting, paging and including related data.

You can download complete project here.

Post to Twitter

ESRI Developer Meet-up Keynote

As I already mentioned, I delivered keynote at ESRI Developers Meet-up in Atlanta last week.  I wanted to post my short speech, as it expresses some very important points.  I talked about Microsoft developer landscape and importance of learning.  Here is the speech.  Please let me know what you think.

ESRI Key note

My name is Sergey Barskiy. I live here in Atlanta, and I work for Magenic Technologies, a Microsoft technology focused consulting company. I appreciate the opportunity to express my opinion on Microsoft technology landscape as it currently stands, with focus on Windows Phone 7, Silverlight and cloud technology stack.

Let me start with a quote attributed to Buddha. “Everything changes, nothing remains without change.”

Let’s start with the Windows Phone 7. The first phones were sold last November time frame. So far more than a million phones have been sold, which some think is a success and some a failure. Instead of talking about subjective opinions on the WP 7, let’s discuss what this release did for Microsoft. This release is arguably the first consumer oriented phone device that Microsoft put out. It is in direct completion with iPhone and Android phones. Marketplace has become very important on that market, and Microsoft put very heavy focus on that aspect of the phone. Microsoft tools have always been very good, but tools for phone were extremely well done, considering that was the first release of the tool set. So far there are over 12,000 applications in marketplace, and much more by some estimates, maybe as many as 20,000. There are tens of thousands of developers registered with the marketplace. It is hard not to say that this is not a success for Microsoft. New beta release of tools for the next revision of the phone, dubbed Mango, shipped a few weeks ago. It contains many consumer oriented as well as developer oriented features. Consumer features ultimately matter more, because phone needs to make users happy before making developers happy. Out of those features IE9 and HTML 5 support is probably the most important. Along with it users will enjoy fast application switching, better office integration and improved multi tasking. These feature set demonstrate ongoing commitment and maturation of the platform. Developers’ features include background tasks, SQL CE with ORM, better camera integration, compass access and better tooling, specifically emulator features such as GPS and accelerometer support. There will also be better integration between two developer platform on phone, XNA and Silverlight. Of course, ESRI has its own powerful API for the phone.

Let’s now move on to Silverlight. There has been some controversy about future of Silverlight, especially after comments by Bob Muglia last fall. In response to this negativity, Microsoft announced Silverlight 5 features a while ago, reaffirming its commitment to Silverlight platform in general. The beta shipped a a few weeks ago. Having said that, Microsoft’s message around Silverlight has changed since Silverlight 2 was released. It changed from cross platform cross browser application development platform to just developer platform for media applications and business applications. Since there is no mentioning of cross platform any longer, one could deduce that the focus is now on Windows development. Let’s take a look at the Silverlight 5 features and see how the next version of the platform and see how they fit into that message.

First of all, media related features. There is a lot of improvement in how media, such as videos are handled. There are performance improvements for hardware decoding and h.264 playback, including low power devices. Trick play was added, allowing the user to play videos at high speed, while correcting sounds for pitch changes. Improved power awareness keeps screen saver from coming up while media is playing. Remote control capabilities were added as well as some DRM enhancements. Enhancements to text presentation were added, allowing for text flow around images; text layout speed was increased. Performance across the board was also a focus. Graphics engine also improved, providing for more GPU acceleration as well as 3D support.

On the other hand, developer experience was taken into account. Default templates for types are now supported, allowing UI to automatically pick a template when a view model is injected into the visual tree. Additional binding options are appearing in this release, namely DataContextChanged event, XAML binding debugging, relative source binding to ancestor, proving more power for creating custom controls and custom templates. Profiling features allow for better troubleshooting of slow parts of a complex system.

There are some Windows related features as well, such as 64 bit plug-in availability. There are enhancements to out-of-browser functionality, such as multiple windows in out-of-browser mode. There is more support for process launching and PInvoke, enabling developers to write applications that integrate better with Windows desktop.

Of course, we cannot talk about Silverlight without mentioning HTML, the 10,000 pounds gorilla in the room. Based on announcement and comments from various Microsoft folks and public blogs, HTML 5 is now the official Microsoft answer for cross platform development. As to what tools can be used, those would include ASP.NET and ASP.NET MVC from Microsoft perspective. Does this mean Silverlight is dead? By no means, it just has different goals from the ones 3 years ago. It is still very much a viable platform for business applications, as long as requirements support the usage of the platform. Let’s chat about MVC 3.0, since it was also released this year.

In general, ASP.NET MVC is very powerful platform for web development. It addresses some of the issues that plagued ASP.NET. MVC gently enforces separation of concerns and improved testability of applications. Its output is platform independent. It results (one could hope anyway) in clean applications. There is no ViewState in those applications, hence in theory they should perform faster. There is no easy way to put code behind into views, although not necessarily impossible. Developers are very close to the metal, HTML in this case and JavaScript. Razor view engine that is new in version 3.0 improves view creation experience, resulting in less overall code.

Now let’s chat about cloud. In general terms cloud refers to delegating maintenance of some parts of your application, sometimes hardware, sometimes also run time to a third party provider. There are a few types of cloud platforms. IAAS – infrastructure as a service means that hardware is provided by cloud provider, and the consumer is responsible for setting up their applications and maintaining them. In typical sense this means running virtual machines in the cloud, otherwise known as some data center full of computers maintained by a cloud company. Another type is SAAS or software as a service. This means you rent the software from a company, and they are responsible for everything. An example would be SalesForce. Third and arguably most interesting aspect is PAAS or platform as a service. In this approach cloud provider supplies virtual machines preloaded with software and supplies tools for the developer to deploy and monitor software that utilizes all aspects of the platform, such as operating system, additional software and resources.

Why use the cloud? There are a number of reasons that vary from product to product. Typically reasons would include cost of entry, scalability, availability and geo-proximity. Say you wrote a brand new exciting web product, but you are not sure how many customers you will have. Could be one, could be 1 million. So you struggle with the question how much hardware and software to provision. Both under and over-provisioning are problems. If you under provision and your software’s performance is bad, the customer will run away from you. If you over provision you may spend millions for no reason. Cloud aims to solve this problem by providing on demand growth opportunity, otherwise known as pay-as-you-go model. Hand in hand with this goes scalability. Properly written software is easily scalable, usually with a couple of button clicks. Cloud vendor usually guarantees uptime of your system, thus insuring your software is available to be used. Geo-proximity allows you to position servers closer to customer, including abroad.

Let’s take a look at Microsoft presence in this space. Microsoft has offering in both SAAS and PAAS sectors of the market. SSAS includes a number of products. The most prominent one is Office 365, which include Office Professional, Outlook on line, Link which is the successor to Communicator and Live Meeting and SharePoint online. This offering allows you for just a few bucks per person per month remove a lot of pains from organizational activities that do not directly contribute to overall value of the company. This is really simple offering, and not very interesting if you are a developer.

Much more interesting is PAAS or Windows Azure. Let’s take a closer look at what Azure offers to developers, and as a result to your customers.

At a high level Windows Azure comes with a number of options to develop applications with. First and foremost, it is Windows itself and .NET framework. You further utilize the following roles available in Azure: Web role and Worker role. Web role is designed to host web applications, such as ASP application. Worker role is akin to Windows services. Its purpose is to provide sheer computing power and processing power. You have a number of storage options on Azure. You can utilize SQL Azure which is relational database in the cloud, build on SQL Server 2008. It has all the familiar features to all the developers. Furthermore you can use blob storage, suitable for storing large files, such as videos or documents. This storage is http addressable via a URL, and can be used as a result in all web applications. Developers also have table storage available. It can be used to store structure, but non-relational data. It is much cheaper than SQL Azure and much more scalable, but it is up to you to maintain transactional integrity. And finally you can also use message queues, which are durable messages that can be used to communication information between parts of one application or multiple applications. SSRS is already in beta as well, providing a complete solution for business applications.

Another very important part of Azure offering is AppFabric. AppFabric is an umbrella term used to describe a number of helpful technologies. They include Service Bus, Access Control, Caching, Integration, and Composite App (WCF/WF Hosting). Let’s break them up and take a closer look at each one.

The Service Bus provides secure messaging and connectivity capabilities that enable building distributed and disconnected applications in the cloud, as well hybrid application across both on-premise and the cloud. It enables using various communication and messaging protocols and patterns, and saves the need for the developer to worry about delivery assurance, reliable messaging and scale.

Access Control provides an easy way to provide identity and access control to web applications and services, while integrating with standards-based identity providers, including enterprise directories such as Active Directory® (ADFS 2.0), and web identities such as Windows Live ID, Google, Yahoo! and Facebook. The service enables authorization decisions to be pulled out of the application and into a set of declarative rules that can transform incoming security claims into claims that applications understand. These rules are defined using a simple and familiar programming model, resulting in cleaner code. It can also be used to manage users’ permissions, saving the effort and complexity of developing these capabilities.

Caching provides a distributed, in-memory, application cache service for Windows Azure and SQL Azure applications. It provides applications with high-speed access, scale, and high availability, to application data. These capabilities are provided entirely as a service (no installation or management of instances, dynamically increase/decrease cache size as needed).

Integration provides common BizTalk Server integration capabilities (e.g. pipeline, transforms, adapters) on Windows Azure, using out-of-box integration patterns to accelerate and simplify development. It also delivers higher level business user enablement capabilities such as Business Activity Monitoring and Rules, as well as self-service trading partner community portal and provisioning of business-to-business pipelines.

Composite App provides a multi-tenant, managed service which consumes the .NET based AppFabric Composition Model definition and automates the deployment and management of the end to end application, eliminating manual steps needed by both developers and IT Pros today. It directly executes application components to provide a high-performance runtime optimized for cloud-scale services and mid-tier components. It also delivers a complete hosting environment for web services built using Windows Communication Foundation (either natively developed or using WCF Data Services and WCF RIA Services) and workflows built using Windows Workflow Foundation.

Finally, we cannot really end without mentioning Windows 8. I am not sure how many of you follow current rumors and have seen a video put out by Microsoft that shows a glimpse of Windows 8. They showed Metro or Windows Phone 7 interface with live tiles, full gesture support and touch friendly user interface. Moreover, there are various hints as to new programming model for Windows. Does it mean none of the existing applications will run on Windows 8? Of course not. This new functionality has to be additive. Having said that, there are rumors on Mary-Jo Foley blog and WinRumors.com that mention Jupiter as the new API (the best one could decipher) that will be available in Windows 8. There is uproar already in Silverlight community, stating that Microsoft again is abandoning Silverlight. If you could look at Jupiter as new and better API and user experience, then the question is why fight it?

Let me end with another quote by Eric Hoffer, American philosopher.

“In times of profound change, the learners inherit the earth, while learned find themselves beautifully equipped to deal with a world that no longer exists.”

The moral of the story is that Microsoft will never stop inventing new technologies, as this would spell the end to them as a company. So that a developer to do? The answer is never stop learning.

Post to Twitter

Reflections on Blogging

I started my blog here in November 2009 after moving it from Live Spaces, that since died as a project.  My primary goal of starting that is to share my thoughts and experiences with other folks, vet some new ideas, and hopefully help a person or two solve the same problems I found solutions to at some point in time.  Blogging also gives me a place to document my experiences.  In addition any time I research a topic, I like to write about it because the process of writing things down helps me remember better.

This month I hit what I consider a milestone of 100,000 views on my blog!

image

 

Woo-hoo!  I think that is pretty cool!

 

image

This chart shows some steady growth in views over the last 20 months.  I guess I am doing something right if that many folks can find tidbits of useful information in my writings.

Thank you.

Post to Twitter

Conclusion On Repository Pattern with Entity Framework

I have written a number of posts on this pattern lately. One thing that I used in some of them is return IQueryable. The idea behind this is to limit the number of Select methods to one in your repository. This goal is achieved by allowing calling code to append where or order by information to the return value of the repository select method. The downside of that is that you expose part of your implementation to calling code. I do not see a giant problem with this, as sometime this is a legitimate approach. Having said that, what if you would like to be more string in your data access code? This is the idea behind this post.

I am taking the approach of returning IEnumerable<T> instead. This would be pretty generic and does not reveal as much about my implementation. The rest of the CUD methods should be almost the same as in previous post. I am making a small modification to allow for deferred as well as immediate save. In an ideal world, you really should inherit from this class, so I am marking it as abstract. Now that I am returning IEnumerable, am I back in the boat of endless proliferation of Select methods? I am going to avoid this by allowing the calling code to pass in where and order by data in a generic way using Expressions. I am also going to add paging parameters as well. Sometimes you need to pass in Include information to allow passing of additional tables. If you do not want to expose that much, feel free to remove that parameter as well. Now that I know what functionality I would like to have, I am going to create an interface for my repository.

using System;

using System.Collections.Generic;

using System.Linq.Expressions;

namespace EFCodeFirstExtensions

{

public interface IEFCodeFirstRepository : IDisposable

{

/// <summary>

/// Select data from database using a where clause

/// </summary>

/// <typeparam name=”TItem”>Type of data to select</typeparam>

/// <param name=”whereClause”>Where clause / function</param>

/// <param name=”orderBy”>Order by clause</param>

/// <param name=”skip”>Paging implementation = number of records to skip</param>

/// <param name=”top”>Paging implementation = number of records to return</param>

/// <param name=”include”>Navigation properties to include</param>

/// <returns>Items selected</returns>

IEnumerable<TItem> Select<TItem>(

Expression<Func<TItem, bool>> whereClause = null,

OrderByClause<TItem>[] orderBy = null,

int skip = 0,

int top = 0,

string[] include = null)

where TItem : class, new();

/// <summary>

/// Update an item

/// </summary>

/// <typeparam name=”TItem”>Type of item to update</typeparam>

/// <param name=”item”>Item to update</param>

/// <param name=”saveImmediately”>If set to true, saved occurs right away</param>

/// <returns>Updated item</returns>

TItem Update<TItem>(TItem item, bool saveImmediately = true) where TItem : class, new();

/// <summary>

/// Delete an item

/// </summary>

/// <typeparam name=”TItem”>Type of item to delete</typeparam>

/// <param name=”saveImmediately”>If set to true, saved occurs right away</param>

/// <param name=”item”>Item to delete</param>

void Delete<TItem>(TItem item, bool saveImmediately = true) where TItem : class, new();

/// <summary>

/// Insert new item into database

/// </summary>

/// <typeparam name=”TItem”>Type of item to insert</typeparam>

/// <param name=”item”>Item to insert</param>

/// <param name=”saveImmediately”>If set to true, saved occurs right away</param>

/// <returns>Inserted item</returns>

TItem Insert<TItem>(TItem item, bool saveImmediately = true) where TItem : class, new();

/// <summary>

/// Save all pending changes

/// </summary>

void Save();

}

}

There are a couple of helper class I am using for sorting, primarily to handle sort direction in an abstract fashion.

using System;

namespace EFCodeFirstExtensions

{

public enum SortDirection

{

Ascending,

Descending

}

}

using System;

using System.Linq.Expressions;

namespace EFCodeFirstExtensions

{

public class OrderByClause<T>

where T : class, new()

{

private OrderByClause()

{

}

public OrderByClause(

Expression<Func<T, object>> orderBy,

SortDirection sortDirection = SortDirection.Ascending)

{

OrderBy = orderBy;

SortDirection = sortDirection;

}

/// <summary>

/// Order by expression

/// </summary>

public Expression<Func<T, object>> OrderBy { get; private set; }

/// <summary>

/// Sort direction

/// </summary>

public SortDirection SortDirection { get; private set; }

}

}

The implementation is very simple from a high level. I am adding a bit of protection to the update and delete methods to handle the case when entity is already in the context. I am doing this via context API for Entry method. The comment that points to this method is in green below

public TItem Update<TItem>(TItem item, bool saveImmediately = true)

where TItem : class, new()

{

DbSet<TItem> set = context.Set<TItem>();

var entry = context.Entry(item);

if (entry != null)

{

// entity is already in memory

entry.State = System.Data.EntityState.Modified;

}

else

{

set.Attach(item);

context.Entry(item).State = System.Data.EntityState.Modified;

}

if (saveImmediately)

{

context.SaveChanges();

}

return item;

}

The most interesting part is Select method. I handling all parameters in order: where, order by, etc… Since I allow nulls, I am making all parameters optional to allow selection of all rows. Here is full code for my implementation

using System;

using System.Collections.Generic;

using System.Configuration;

using System.Data.Entity;

using System.Linq;

using System.Linq.Expressions;

namespace EFCodeFirstExtensions

{

public abstract class EFCodeFirstRepository<TContext> : IDisposable, IEFCodeFirstRepository

where TContext : DbContext, new()

{

private TContext context;

/// <summary>

/// Create new instance of repository

/// </summary>

public EFCodeFirstRepository()

{

context = new TContext();

}

/// <summary>

/// Set connection string

/// </summary>

/// <param name=”connectionStringName”>Connection string name from .config file</param>

public void SetConnectionString(string connectionStringName)

{

context.Database.Connection.ConnectionString =

ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString;

}

/// <summary>

/// Select data from database using a where clause

/// </summary>

/// <typeparam name=”TItem”>Type of data to select</typeparam>

/// <param name=”whereClause”>Where clause / function</param>

/// <param name=”orderBy”>Order by clause</param>

/// <param name=”skip”>Paging implementation = number of records to skip</param>

/// <param name=”top”>Paging implementation = number of records to return</param>

/// <param name=”include”>Navigation properties to include</param>

/// <returns>Items selected</returns>

public IEnumerable<TItem> Select<TItem>(

Expression<Func<TItem, bool>> whereClause = null,

OrderByClause<TItem>[] orderBy = null,

int skip = 0,

int top = 0,

string[] include = null)

where TItem : class, new()

{

IQueryable<TItem> data = context.Set<TItem>();

// handle where

if (whereClause != null)

{

data = data.Where(whereClause);

}

//handle order by

if (orderBy != null)

{

int iteration = 0;

orderBy.ToList().ForEach(one =>

{

if (iteration == 0)

{

if (one.SortDirection == SortDirection.Ascending)

{

data = data.OrderBy(one.OrderBy);

}

else

{

data = data.OrderByDescending(one.OrderBy);

}

}

else

{

if (one.SortDirection == SortDirection.Ascending)

{

data = ((IOrderedQueryable<TItem>)data).ThenBy(one.OrderBy);

}

else

{

data = ((IOrderedQueryable<TItem>)data).ThenByDescending(one.OrderBy);

}

}

iteration++;

});

}

// handle paging

if (skip > 0)

{

data = data.Skip(skip);

}

if (top > 0)

{

data = data.Take(top);

}

//handle includes

if (include != null)

{

include.ToList().ForEach(one => data = data.Include(one));

}

foreach (var item in data)

{

yield return item;

}

}

/// <summary>

/// Insert new item into database

/// </summary>

/// <typeparam name=”TItem”>Type of item to insert</typeparam>

/// <param name=”item”>Item to insert</param>

/// <param name=”saveImmediately”>If set to true, saved occurs right away</param>

/// <returns>Inserted item</returns>

public TItem Insert<TItem>(TItem item, bool saveImmediately = true)

where TItem : class, new()

{

DbSet<TItem> set = context.Set<TItem>();

set.Add(item);

if (saveImmediately)

{

context.SaveChanges();

}

return item;

}

/// <summary>

/// Update an item

/// </summary>

/// <typeparam name=”TItem”>Type of item to update</typeparam>

/// <param name=”item”>Item to update</param>

/// <param name=”saveImmediately”>If set to true, saved occurs right away</param>

/// <returns>Updated item</returns>

public TItem Update<TItem>(TItem item, bool saveImmediately = true)

where TItem : class, new()

{

DbSet<TItem> set = context.Set<TItem>();

var entry = context.Entry(item);

if (entry != null)

{

// entity is already in memory

entry.State = System.Data.EntityState.Modified;

}

else

{

set.Attach(item);

context.Entry(item).State = System.Data.EntityState.Modified;

}

if (saveImmediately)

{

context.SaveChanges();

}

return item;

}

/// <summary>

/// Delete an item

/// </summary>

/// <typeparam name=”TItem”>Type of item to delete</typeparam>

/// <param name=”saveImmediately”>If set to true, saved occurs right away</param>

/// <param name=”item”>Item to delete</param>

public void Delete<TItem>(TItem item, bool saveImmediately = true)

where TItem : class, new()

{

DbSet<TItem> set = context.Set<TItem>();

var entry = context.Entry(item);

if (entry != null)

{

// entity is already in memory

entry.State = System.Data.EntityState.Deleted;

}

else

{

set.Attach(item);

context.Entry(item).State = System.Data.EntityState.Deleted;

}

if (saveImmediately)

{

context.SaveChanges();

}

}

/// <summary>

/// Save all pending changes

/// </summary>

public void Save()

{

context.SaveChanges();

}

/// <summary>

/// Dispose context

/// </summary>

public void Dispose()

{

if (context != null)

{

context.Dispose();

}

}

}

}

As you can see, there is a variety of ways to implement the pattern, with a number of people usually defending passionately one approach or another. My, I am in a pragmatic camp, trying to get things done. Hence, feel free to use whichever version you like best.

There is one known issue with the code above. You cannot use certain types for order by clause. This is because of the issue with Expression<T, object> with cause issue with Linq trying to case something like int to object. I am going to try to find an answer to that and blog about it.

Email me any questions you might have.

Post to Twitter

CodeStock Talks

I am doing two talks at CodeStock event on Saturday, June  2011.  Tomorrow in other words Smile.

I am talking on two topics. 

Since I would like to share my slides and sample code, you can download two zip files – one for each session.  You can download each one by clicking on the title above.

Thank you.

Post to Twitter

Atlanta Code Camp 2011 is Almost Here

This event is unique in that it is “for the community, by the community” and is free for all that desire to attend. In past years, the Atlanta Code Camp has provided free training and networking opportunities for 300 of the best, most motivated development professionals. With our larger facility, we’re expecting this year to be even bigger and better.

Please check out Code Camp web site for more information.  There are links there for registration, sponsors and volunteers.

Thank you.

Post to Twitter

More on Client Validation in ASP.NET MVC 3

I posted a while ago on asynchronous saves in MVC 3.  One thing to note that after the new content is loaded into the browser, client side validation is broken.  The reason being is that content is only parsed once by unobtrusive jQuery validation.  To fix this issue I would need to force the validator to parse the content again.  Here is what my JavaScript to submit the form would look like now (changes from previous post are in bold)

@if (false)

{   <script src="../../Scripts/jquery-1.5.1-vsdoc.js" type="text/javascript"></script>}

@model MvcEFCodeFirst.Data.Attendee

@{

  Layout = "~/Views/Shared/_Layout.cshtml";

}

<h2>

  @ViewBag.Title</h2>

<div id="formDiv">

  @{Html.RenderPartial("AttendeePartial", Model);}

</div>

<div>

  <button id="saveNewAttendee">

    @ViewBag.ButtonText

  </button>

</div>

<div>

  @Html.ActionLink("Back to List", "Index")

</div>

<script type="text/javascript">

  $().ready(function () {

    $(‘#saveNewAttendee’).click(function () {

      if (!$(‘form’).valid()) {

        return false;

      }

      $.blockUI({ message: ‘<h1>Updating…</h1>’ });

      $.ajax({

        type: "POST",

        url: "./CreateUpdateAjax",

        data: $(‘form’).first().serialize(),

        success: function (data, status, xhr) {

          $(‘#formDiv’).html(data);

          if ($(‘#AttendeeID’).val() != undefined) {

            $(‘#saveNewAttendee’).html(‘Save’);

          };

          $.unblockUI();

          jQuery.validator.unobtrusive.parse(‘form’);

        },

        error: function (xhr, status, error) {

          $.unblockUI();

          alert("error");

        }

      });

    })

 

  })

 

</script>

 

I also would like to spend a bit of time on custom client side validation that is not built based on attributes in POCO classes of Entity Framework.  There are two types of this kind of validation.  One that can be done completely on client side and another that requires a database access or some other information from the server.  I am going to chat about latter first.

I can accomplish this task via Remote attribute.  All I need to do is decorate a property with this attribute to force validation to invoke a controller method when data changes for that property.  This is still accomplished via unobtrusive JavaScript validation. What you need to do is decorate a property you are validating with Remote attribute and specify what method on controller needs to be invoked as well as additional fields to pass to the method and error message to show.  The method just needs to return true or false, where or not the validation passes.  Here is an example of the property decorated with the attributes.

 

    [Remote(

      "DuplicateEmail",

      "Attendee",

      AdditionalFields = "AttendeeID",

      ErrorMessageResourceName = "DuplicateEmail",

      ErrorMessageResourceType = typeof(Resource))]

    public string Email { get; set; }

 

What I am trying to do above is validate to see if the email is a duplicate.  I am passing Attendee ID to the method as well to make sure email is not a duplicate, but I have to filter our current record.  Word attendee is the name of the controller, of course you have to omit word controller out of the call, since this is how MVC is building ajax call.  Here is what my controller method looks like

    public JsonResult DuplicateEmail(string email, int? attendeeID)

    {

      int id = attendeeID.HasValue ? attendeeID.Value : 0;

      return Json(!db.Select<Attendee>()

        .Where(one => one.Email == email && one.AttendeeID != id).Any(),

        JsonRequestBehavior.AllowGet);

    }

 

 

The query using Entity Framework Code First is very simple and does not need much explanation.  What I notice is that my parameters are matched based on names and automatically parsed for me.  Attendee ID is nullable because for brand new attendee entry is not populated yet.  Here is code from my view to show why.

    @if (Model.AttendeeID > 0)

    {

      @Html.HiddenFor(model => model.AttendeeID)

    }

 

I am only dumping ID for existing rows, i.e. for editing, not new attendee creation.  I also use this fact to conditionally edit or create new row.  You can see that in the JavaScript method on top if this post.  All this data gets translated into unobtrusive JavaScript validation calls on the client.  In the next post I will talk about the other side of custom client validation based on IClientValidatable interface.

Thanks.

Post to Twitter

Atlanta Code Camp 2011

Atlanta Code Camp 2011 is in the planning stages.  The event will occur on June 25th.  If you would like to volunteer at the event, please contact me using Contact Me page on this blog.  We are also looking for sponsors.  Please email me if you are interested.  More information will be forthcoming in a few days.  Please stay tuned.

Thank you.

Post to Twitter

Asynchronous Controllers Calls to Save Data in ASP.NET MVC 3

On a few occasions I wondered if it is possible to simulate Silverlight Save behavior in ASP.NET MVC.  What I mean is to asynchronously call a service from an edit form, asynchronously process the results, and update view based on saved data.  This process is a bit more complicated in ASP.NET MVC because we have to process potential errors and update UI to include errors.  Here is the workflow I am trying to implement:

Create new entry screen –> Hit Save –> Submit data to the controller –> Save data –> Return updated view –> Update UI based on updated View, including populating newly generated ID for subsequent saves.

Here is my solution outline

  • Create partial view for the form to enter data for an entity, Attendee in my case.
  • Create Controller method to accept Attendee data from UI to save
  • Return new partial view from this method
  • Push new view into DOM.

I am now going to break down my solution.  I am using the following Attendee class as the entity for entry screen.

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.ComponentModel.DataAnnotations;

using MvcEFCodeFirst.Resources;

 

namespace MvcEFCodeFirst.Data

{

  public class Attendee

  {

    [Key]

    public int AttendeeID { get; set; }

 

    [StringLength(50,

      ErrorMessageResourceName = "FirstName50Chars",

      ErrorMessageResourceType = typeof(Resource))]

    [Required(

      ErrorMessageResourceName = "FirstNameRequired",

      ErrorMessageResourceType = typeof(Resource))]

    [Display(Name = "FirstName", ResourceType = typeof(Resource))]

    public string FirstName { get; set; }

 

    [StringLength(50,

      ErrorMessageResourceName = "LastName50Chars",

      ErrorMessageResourceType = typeof(Resource))]

    [Required(

      ErrorMessageResourceName = "LastNameRequired",

      ErrorMessageResourceType = typeof(Resource))]

    [Display(Name = "LastName", ResourceType = typeof(Resource))]

    public string LastName { get; set; }

 

    [StringLength(250)]

    [Required(

     ErrorMessageResourceName = "EmailRequired",

     ErrorMessageResourceType = typeof(Resource))]

    [RegularExpression(

      @"^[A-Za-z0-9](([_\.\-]?[a-zA-Z0-9]+)*)@([A-Za-z0-9]+)(([\.\-]?[a-zA-Z0-9]+)*)\.([A-Za-z]{2,})$",

      ErrorMessageResourceName = "EmaiInvalidFormat",

      ErrorMessageResourceType = typeof(Resource))]

    [Display(Name = "Email", ResourceType = typeof(Resource))]

    public string Email { get; set; }

 

    [StringLength(int.MaxValue)]

    [Display(Name = "Notes", ResourceType = typeof(Resource))]

    public string Notes { get; set; }

 

    public virtual ICollection<Session> Sessions { get; set; }

  }

}

 

Now I am going to use scaffolding to create new controller that is linked to Attendee class:  I am right-clicking on Controllers folder and selecting new Controller item

 

image

The create, display, etc… views have been created.  Now, I am going to extract form screen for Attendee edit into a partial view.  Here is what this wizard screen looks like.

image

 

The view is pretty simple, and here is what it looks like:

@model MvcEFCodeFirst.Data.Attendee

@using (Html.BeginForm(new { Id = "AttendeeForm" }))

{

  @Html.ValidationSummary(true)

  <fieldset>

    <legend>Attendee</legend>

    <div class="editor-label">

      @Html.LabelFor(model => model.FirstName)

    </div>

    <div class="editor-field">

      @Html.EditorFor(model => model.FirstName)

      @Html.ValidationMessageFor(model => model.FirstName)

    </div>

    <div class="editor-label">

      @Html.LabelFor(model => model.LastName)

    </div>

    <div class="editor-field">

      @Html.EditorFor(model => model.LastName)

      @Html.ValidationMessageFor(model => model.LastName)

    </div>

    <div class="editor-label">

      @Html.LabelFor(model => model.Email)

    </div>

    <div class="editor-field">

      @Html.EditorFor(model => model.Email)

      @Html.ValidationMessageFor(model => model.Email)

    </div>

    <div class="editor-label">

      @Html.LabelFor(model => model.Notes)

    </div>

    <div class="editor-field">

      @Html.EditorFor(model => model.Notes)

      @Html.ValidationMessageFor(model => model.Notes)

    </div>

    @if (Model.AttendeeID > 0)

    {

      @Html.HiddenFor(model => model.AttendeeID);

    }

  </fieldset>

}

 

Now, I am going to integrate this new partial view into Create/Edit shell views for Attendee.  I am going to consolidate Create and Edit views into single view.  This is more complicated now, and I am going to document the code below in more details

@if (false)

{   <script src="../../Scripts/jquery-1.5.1-vsdoc.js" type="text/javascript"></script>}

@model MvcEFCodeFirst.Data.Attendee

@{

  Layout = "~/Views/Shared/_Layout.cshtml";

}

<h2>

  @ViewBag.Title</h2>

<div id="formDiv">

  @{Html.RenderPartial("AttendeePartial", Model);}

</div>

<div>

  <button id="saveNewAttendee">

    @ViewBag.ButtonText

  </button>

</div>

<div>

  @Html.ActionLink("Back to List", "Index")

</div>

<script type="text/javascript">

  $().ready(function () {

    $(‘#saveNewAttendee’).click(function () {

      $.blockUI({ message: ‘<h1>Updating…</h1>’ });

      $.ajax({

        type: "POST",

        url: "./CreateUpdateAjax",

        data: $(‘form’).first().serialize(),

        success: function (data, status, xhr) {

          $(‘#formDiv’).html(data);

          if ($(‘#AttendeeID’).val() != undefined) {

            $(‘#saveNewAttendee’).html(‘Save’);

          };

          $.unblockUI();

        },

        error: function (xhr, status, error) {

          $.unblockUI();

          alert("error");

        }

      });

    })

 

  })

 

</script>

 

 

The top of the file is imply there to get IntelliSense for jQuery.  The next interesting code is RenderParital call.  This is only used during initial call to the view.  The form that is used for data entry is within partial view.  The last portion is javascript that is used to post the form.  First of all I need to block UI while the save is proceeding.  I downloaded and am using blockUI jQuery extension. You can download it here.  Next, I am using ajax method to submit the form data.  I am using convenient serialize method to serialize the form’s fields to be sent to the server.  I am using POST method to submit the data.  I am also specifying error and success functions.  In success function I have to first check to see if the save succeeded to create new Attendee.  I am checking this by inspecting a hidden field for Attendee ID that should have been inserted after successful save.  Then, I unblock UI.

Now, let’s see what the controller method CreateUpdateAjax looks like:

    [HttpPost]

    public ActionResult CreateUpdateAjax(Attendee attendee)

    {

      if (ModelState.IsValid)

      {

        if (attendee.AttendeeID == 0)

        {

          db.Insert(attendee);

        }

        else

        {

          db.SetModified(attendee);

          db.Save();

        }

      }

      return PartialView("AttendeePartial", attendee);

    }

 

This method is very simple.  I am relying on MVC to convert form data magically into an Attendee object.  Then I am checking for errors.  If everything succeeds, I am inserting or updating the attendee using my repository class, then returning a partial view.  I am skipping repository for now, you can read about it in my previous posts.  Just search for repository in top right corner of the blog.

In conclusion as you can see it does not take much more code to simulate Silverlight behavior in ASP.NET MVC.  Of course, if you try to create a one-page MVC application, you will find that you will need to write a lot more code.  Then again, do your users expect a single page web application?  Anyway, my goal in this post was to show how to do asynchronous saves, and I thinks this approach works pretty well.

Thanks.

Post to Twitter

ESRI Developers’ Meet Up in Atlanta

I will be delivering keynote at the local ESRI development meeting in Atlanta, GA next month.  Meeting will be held at Maggiano’s in Buckhead at 5 pm.  I will be talking about current application development landscape using Microsoft technologies.  I will be touching on Azure platform, phone development, Silverlight 5.0,  ASP.NET MVC and data platform landscape.

You can register to attend here http://www.meetup.com/DevMeetUpSoutheast/events/17703001/

Thanks.

Post to Twitter

Microsoft Tech Ed 2011 Keynote

Today’s keynote was about two topics – Cloud and Devices.

Cloud topic was first.  Here is what Microsoft Corporate VP talked about.  He relayed Microsoft’s perspective as to why cloud is important and why it will continue to grow and play an important role for many companies.  Three primary reasons are agility, focus and economics.  Agility refers to companies’ ability to scale on demand, utilizing pay-as-you-go model. Focus refers to concentration of corporations on core software products and technologies instead of worrying about infrastructure.  And economics refers to decrease need to invest large amounts of money into hardware and licenses.  All these ideas are valid and important. 

Next announcements underscored Microsoft’s realization that private cloud is just as if not more important than public cloud.  The rest of the talk applied equally to public and private cloud.  Presenters talked about Microsoft System Center 2012 codename Concero as the next generation product that will enable users to manage and maintain their cloud offerings.

Next they talked about BI and data.  They underscored two important concepts the next generation of Microsoft software is going to address – insight and oversight.

Insight means allowing users, mostly business users to slice and dice the data as they see fit to gather important information from tons of collected data points.  PowerPivot, SharePoint and project Crescent that will ship with next generation of SQL Server were mentioned.  Crescent looks like PowerPivot which shipped a while ago on steroids, with ability to visualize data in many ways in addition to ability to view it.  Crescent will be integrated into SharePoint to give other users insight into gathered data via report / Crescent project sharing as well as oversight, since user actions will be captured in SharePoint.  Developer will be able to convert these business users’ created project into Visual Studio projects.

Next set of topic points refered to devices.  Average number of connected devices per adult in the US is 4.3.  Microsoft sees this number growing in the future, and growing rapidly.  The range of devices vary, and includes phones and tablets.  Mango, the next version of OS for Windows Phone 7 has many features that are intended to entice not only general public, but also corporate users.  These features include Lync (next generation of communication software, which includes some features of Communicator and Live Meeting) on the phone as well as corporate security features and Office 365 integration.

Kinect was also mentioned with World Wide Telescope being a flag ship product that identifies strengths of the Kinect platform in education.  Also a medical product was showcased that uses Kinect in an operation room.

Windows Phone was the next topic.  Windows phone toolkit for Azure was mentioned as the tool that can speed up development quite a bit if you are coding that type of application.

TFS v. next was the next topic.  One of the goals for the next release is to bring stakeholders and operations folks into the conversion.  Stakeholders will be able to prototype features using PowerPoint.  Operations manager will be able to create TFS work items directly from system center software using system center connector, and include relevant information such as stack trace.   IntelliTrace will be available in production as the integration point between operations and development.  Developers also get some new features, such as My Work tab that identifies the work items assigned to developers.  Developers will be able to handle interruptions better via “Save / Restore My Work” feature.

OK, at a high level this is what Microsoft guys talked about in the key note.  Now it is the time for my personal opinion.  After all, why have a blog if you cannot express yourself.

One thing that jumped at me was low energy level of all presenters.  Maybe they were tried after travel?  Also, there were very few announcements that I have not heard before at different events or have not read on blogs.  Ideally I would have liked to hear a little more about other technologies, such as web or Silverlight.  I know that TechEd is supposed to be about IT as well as Dev, but one could hope for more pertinent information.  Some of the jokes were a little stale to my taste, the usual “I am your boss, so drop everything and do this” jokes get old.  Maybe Microsoft should hire a comedian to help them next time.

Now some takeaways.  One message that was pretty clear was directed toward IT professionals.  They need to be up to speed on Azure, or they will be left behind.  Private cloud is coming, and companies need to consider if that technology suits them.  IMHO, private clouds are diminishing the value of cloud in general, but with the right tooling the gains are still there, although investment into hardware is still pretty big.  Message for developers regarding TFS is clear as well.  This product will continue to grow to help companies to collaborate, develop, test and operate software.  In devices marker Mango version of the Windows Phone OS will provide a number of cool new features that will undoubtedly advance its standing amongst consumers and enterprises.  Now we just have to wait and see if Microsoft marketing can do its job to let masses know what is coming soon.

Thank you.

Post to Twitter

Using WinDbg to Troubleshoot WCF Performance Issues

Yesterday I was working on a very interesting problem.  I am involved in developing a Silverlight application that is using WCF Services to communicate with a server to perform CRUD and business logic related operations.  All of a sudden QA started experiencing very slow performance testing application at random times.  Once we took a look, we noticed that CPU utilization kept hovering around 100 % at those times.  I was trying to figure out what is causing high CPU utilization.  Typically, those issues would be linked to tight loops of sorts, that tend to peg CPU at near maximum.  In our case, once CPU got to 100 %, it stayed there until app pool was recycled.  Give the tight loop hunch, I was guessing that somehow a service process was getting stuck in an infinite loop or some heavy processing loop. 

I blogged previously on using WinDbg to debug memory leaks in Silverlight applications.  It was time to find out if WinDbg would help me in this case as well.  The following describes the steps I took to troubleshoot the problem.

First of all, use steps in the previous post to install debugging tools for Windows.

Then, you need to catch the IIS process when it is in high SPU utilization mode.  You should let the system sit there for a little while to ensure you will capture the procedures that cause the trouble.  At that time open command window and switch to debugging tools directory.  In 64 bit Windows it is C:\Program Files\Debugging Tools for Windows (x64).  At the command prompt type “adplus -hang -o c:\dump\ -IIS”.  This will create process dump in c:\dump folder for all IIS related processes.

This you can reset IIS.

Next step is to run WinDbg and open a dump file using File->Open Crash Dump menu.  You will have multiple files with “dmp” extension in C:\Dump\<Time-Stamp> folder that was just created.  I’d pick the largest one, since this is likely to belong to your process.

Now, load debug symbols by typing the following into command window (one line high windows in the bottom of the WinDbg windows.).  Your cursor should be blinking there.  .load C:\Windows\Microsoft.NET\Framework64\v4.0.30319\sos.dll.  If you use 32 bit framework, adjust location accordingly.

image

Then, type “!runaway” command to get the list of running threads sorted by CPU time, starting the longest running thread.  If you suspect a hang, it is likely that your problem causing threads will be listed first.

image

Then, we will “select” a thread by using thread command – “~XXs”, where XX is the thread number from !runaway command.  In my case those are threads 18 and 30, sot the command would be ~18s

Now, we can look at the thread stack by using the following command – “!clrstack”.

 

image

What we are interested in is the very first line that points to PerfDemoWcfService.Service1.GetData method.  This is the method that causes the issue.  In my sample case methods…

  public class Service1 : IService1

  {

    public string GetData(int value)

    {

      Int64 variable = 0;

      while (true)

      {

        if (variable > 1000000000)

        {

          variable = 0;

        }

        else

        {

          variable++;

        }

      }

      return string.Format("You entered: {0}", value);

    }

 

 

… looks ridiculous.  In my real case it was a lot more complicated, but I did know what method is causing troubles for me.

 

Thanks.

Post to Twitter

Windows Phone 7 Unleashed Hackathon

Monday, May 16, 2011

6:00p.m. to 11:00 p.m.

Register:  http://bit.ly/RegWP7Hackathon

Don’t miss this opportunity to get hands on help with your Windows Phone 7 app, from the experts!

This is a "hands on" hackathon where you will learn from Windows Phone 7, XNA and Azure experts how to build, scale and publish your Windows Phone 7 app or game.  If you are just a beginner, or already have apps in the Marketplace this event will should not be missed.

BYO Laptop! 

RSVP early, space is limited to 300 attendees:  http://bit.ly/RegWP7Hackathon

Food, beverages and refreshments will be provided.

Omni Hotel At CNN Center

Grand Ballroom (A,B, C)

100 CNN Center

Atlanta, Georgia  30303

Post to Twitter

Events and Lambda Expressions

Something I was pondering about today.  Say, I have a class and I would like to subscribe to an event it raises, handle it once, and unsubscribe.  Pretty easy scenario, and the code is just as simple.

Here is my simple class with event arguments:

using System;

 

namespace EventsDemo

{

  public class EventProvider

  {

    public string RandomData { get; set; }

 

 

    public void RaiseEvent()

    {

      OnRandomEvent(RandomData);

    }

 

    public event EventHandler<RandomEventArgs> RandomEvent;

 

    protected void OnRandomEvent(string data)

    {

      if (RandomEvent != null)

      {

        RandomEvent(this, new RandomEventArgs(data));

      }

    }

  }

}

 

using System;

 

namespace EventsDemo

{

  public class RandomEventArgs : EventArgs

  {

    private RandomEventArgs() { }

 

    public RandomEventArgs(string data)

    {

      Data = data;

    }

    public string Data { get; private set; }

  }

}

 

Of course, my console sample application is just as easy:

using System;

 

namespace EventsDemo

{

  class Program

  {

    static void Main(string[] args)

    {

      string extraData = "extra data";

 

      EventProvider provider = new EventProvider() { RandomData = "something" };

      provider.RandomEvent += new EventHandler<RandomEventArgs>(provider_RandomEvent);

      provider.RaiseEvent();

      Console.ReadKey();

    }

 

    static void provider_RandomEvent(object sender, RandomEventArgs e)

    {

      Console.WriteLine(e.Data);

      EventProvider provider = sender as EventProvider;

      provider.RandomEvent -= new EventHandler<RandomEventArgs>(provider_RandomEvent);

    }

 

 

  }

}

 

However, I am accustomed to just handle events as lambda expressions as I find that syntax much cleaner and easier to follow:

 

using System;

 

namespace EventsDemo

{

  class Program

  {

    static void Main(string[] args)

    {

      string extraData = "extra data";

 

      EventProvider provider = new EventProvider() { RandomData = "something" };

      provider.RandomEvent += (o, e) => { Console.WriteLine(e.Data); };

 

      provider.RaiseEvent();

      Console.ReadKey();

    }

 

 

  }

}

 

Now is the question.  How do I unsubscribe from the event in my lambda expression?  I cannot do what I did before, since I do not have a handler to use for –= call.  So, I have to declare my handler separately.  Here is modified code:

using System;

 

namespace EventsDemo

{

  class Program

  {

    static void Main(string[] args)

    {

      string extraData = "extra data";

      EventProvider provider = new EventProvider() { RandomData = "something" };

 

      EventHandler<RandomEventArgs> handler = null;

      handler = (o, e) => { Console.WriteLine(e.Data); provider.RandomEvent -= handler; };

      provider.RandomEvent += handler;

 

      provider.RaiseEvent();

 

      provider.RaiseEvent();

 

      Console.ReadKey();

    }

 

 

  }

}

 

I am calling RaiseEvent twice to ensure I did indeed unsubscribe.  Now what is the advantage to this approach you say?  Closures is my number one reason along with clean code as close second.  Here is the final version:

using System;

 

namespace EventsDemo

{

  class Program

  {

    static void Main(string[] args)

    {

      string extraData = "extra data";

      EventProvider provider = new EventProvider() { RandomData = "something" };

 

      EventHandler<RandomEventArgs> handler = null;

      handler = (o, e) => { Console.WriteLine(e.Data + "-" + extraData); provider.RandomEvent -= handler; };

      provider.RandomEvent += handler;

 

      provider.RaiseEvent();

 

      provider.RaiseEvent();

 

      Console.ReadKey();

    }

 

 

  }

}

 

As you can see, I use closure and take advantage of the scope in which my extraData variable is declared, thus combining data in the event with that variable.  I could not do this in my first example without making extraData variable public.  In this quick post I demonstrated how to unsubscribe from events where handlers are implemented as lambda expression as well as outlined the reasons why one might want to use this approach.  Why would you want to unsubscribe?  Typically, your handlers would be cleaned up, but what if your code throws an exception inside lambda expression?  In this case next time you raise the event, it will be handled twice.  Also, I am a big fan of cleaning up event handlers as they are a major source of potential memory leaks.

Thanks.

Post to Twitter

More on Asynchronous Processing in ASP.NET MVC 3

In this post I would like to cover a couple of asynchronous patterns that are available in ASP.NET MVC and jQuery as it is used in MVC.

In all my previous examples related to MVC 3.0 I used regular controller class that is automatically created for a developer when New Item –> Controller is chosen from right-click menu on Controller folder in MVC application project.  Now, there is another type of controller that is available in MVC that is not often used –  AsyncControllerThis controller allows you to break your controller actions into two parts – Begin and End methods used in a typical asynchronous patter.  Just like a lot of other functionality in MVC, this pattern follows the same naming conventions.  For example, if you would like to break “Index” controller action into two methods – begin and end, you would end up with IndexAsync and IndexCompleted methods.  As a result, if you navigate to Index url, the former method will automatically be invoked, and when it flags action as completed, IndexCompleted method will be invoked.  Here is code the illustrates this point, calling database, and more specifically EF Code First, asynchronously.

  public class AttendeeController : AsyncController

  {

    private CodeStockContext db = new CodeStockContext();

 

    //

    // GET: /Attendee/

 

    public void IndexAsync()

    {

      AsyncManager.OutstandingOperations.Increment();

      BackgroundWorker worker = new BackgroundWorker();

      worker.DoWork += (o, e) =>

      {

        using (var context = new CodeStockContext())

        {

          AsyncManager.Parameters["attendees"] = context.Attendees.OrderBy(_ => _.LastName).ThenBy(_ => _.FirstName).ToList();

        }

      };

      worker.RunWorkerCompleted += (o, e) => { AsyncManager.OutstandingOperations.Decrement(); };

      worker.RunWorkerAsync();

 

    }

 

 

    public ViewResult IndexCompleted(IEnumerable<Attendee> attendees)

    {

      return View(attendees);

    }

 

As you can see, there is also parameter matching going on, where parameters of AsyncManager are automatically matched to parameters to Completed method.  The only other interesting point, is Increment and Decrement methods of AsyncManager that keep track of pending operations.  If you have multiple operations, you call increment with a parameter corresponding to a number of asynchronous operations.

Why use this pattern?  It has something to do with how IIS processes requests.  When a request comes in, IIS grabs a worker thread from the pool and processes incoming request on this thread.  If you have too many requests, IIS may run out of available threads.  So, if you have a long running IO bound operation, you can dispatch it on a background thread, thus releasing worker thread back into the IIS pool until it is needed, increasing throughput of your web site.  You can read more on this subject here.

Now, there is one more use for asynchronous processing in MVC.  I would like to demonstrate how to use ajax methods on jQuery.  You can use ajax method or post/get methods.  In my case, I am going to demonstrate how to use post method to submit a form’s data to a controller’s method without postback.  Why do this?  At the expense of complexity, you can develop a user interface very similar to windows forms interface.  So, I would likely not go this route without specific user requirements. 

So, now back to the code.  Here is what my view would look for Create action for a class called Attendee.  Frist, let me show you Attendee class:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.ComponentModel.DataAnnotations;

using MvcEFCodeFirst.Resources;

 

namespace MvcEFCodeFirst.Data

{

  public class Attendee

  {

    [Key]

    public int AttendeeID { get; set; }

 

    [StringLength(50,

      ErrorMessageResourceName = "FirstName50Chars",

      ErrorMessageResourceType = typeof(Resource))]

    [Required(

      ErrorMessageResourceName = "FirstNameRequired",

      ErrorMessageResourceType = typeof(Resource))]

    [Display(Name = "FirstName", ResourceType = typeof(Resource))]

    public string FirstName { get; set; }

 

    [StringLength(50,

      ErrorMessageResourceName = "LastName50Chars",

      ErrorMessageResourceType = typeof(Resource))]

    [Required(

      ErrorMessageResourceName = "LastNameRequired",

      ErrorMessageResourceType = typeof(Resource))]

    [Display(Name = "LastName", ResourceType = typeof(Resource))]

    public string LastName { get; set; }

 

    [StringLength(250)]

    [Required(

     ErrorMessageResourceName = "EmailRequired",

     ErrorMessageResourceType = typeof(Resource))]

    [RegularExpression(

      @"^[A-Za-z0-9](([_\.\-]?[a-zA-Z0-9]+)*)@([A-Za-z0-9]+)(([\.\-]?[a-zA-Z0-9]+)*)\.([A-Za-z]{2,})$",

      ErrorMessageResourceName = "EmaiInvalidFormat",

      ErrorMessageResourceType = typeof(Resource))]

    [Display(Name = "Email", ResourceType = typeof(Resource))]

    public string Email { get; set; }

 

    [StringLength(int.MaxValue)]

    [Display(Name = "Notes", ResourceType = typeof(Resource))]

    public string Notes { get; set; }

 

    public virtual ICollection<Session> Sessions { get; set; }

  }

}

 

Now, in my view I have regular Html form, but without submit input element:

 

@model MvcEFCodeFirst.Data.Attendee

@{

  ViewBag.Title = "Create";

  Layout = "~/Views/Shared/_Layout.cshtml";

}

<h2>

  Create</h2>

@using (Html.BeginForm())

{

  @Html.ValidationSummary(true)

  <fieldset>

    <legend>Attendee</legend>

    <div class="editor-label">

      @Html.LabelFor(model => model.FirstName)

    </div>

    <div class="editor-field">

      @Html.EditorFor(model => model.FirstName)

      @Html.ValidationMessageFor(model => model.FirstName)

    </div>

    <div class="editor-label">

      @Html.LabelFor(model => model.LastName)

    </div>

    <div class="editor-field">

      @Html.EditorFor(model => model.LastName)

      @Html.ValidationMessageFor(model => model.LastName)

    </div>

    <div class="editor-label">

      @Html.LabelFor(model => model.Email)

    </div>

    <div class="editor-field">

      @Html.EditorFor(model => model.Email)

      @Html.ValidationMessageFor(model => model.Email)

    </div>

    <div class="editor-label">

      @Html.LabelFor(model => model.Notes)

    </div>

    <div class="editor-field">

      @Html.EditorFor(model => model.Notes)

      @Html.ValidationMessageFor(model => model.Notes)

    </div>

  </fieldset>

}

<div>

  <button id="saveNewAttendee">

    Create</button>

</div>

<div>

  @Html.ActionLink("Back to List", "Index")

</div>

<script type="text/javascript">

  $().ready(function () {

    $(‘#saveNewAttendee’).click(function () {

      $.post(‘./CreateAjax’, $(‘form’).first().serialize(), function (o) {

        alert(o);

        if (o === ‘OK’)

          window.location.href = ‘./Index’;

      });

 

    })

  })

</script>

 

Now, instead of submit button, you will see a regular button with ID of saveNewAttendee.  In jQuery ready method, I am attaching a click event handler to this button, in which I am simulating the submit method.  I am calling CreateAjax method on my controller, and I am passing data array created by serializing data collected in the form.  All this is available in jQuery.  I am also passing in function that will be fired when method completes.  Here is the code for the controller method:

    [HttpPost]

    public string CreateAjax(Attendee attendee)

    {

      if (ModelState.IsValid)

      {

        db.Attendees.Add(attendee);

        db.SaveChanges();

        return "OK";

      }

 

      return string.Concat(

        ModelState.SelectMany((state) => state.Value.Errors

          .Select(e => e.ErrorMessage + Environment.NewLine)).ToArray());

    }

 

The code is pretty simple.  I am checking to make sure the model is valid, and if it is, I am saving new attendee.  Otherwise, I am create a string containing all error messages using Linq.  ModelState class contains all the validation data you could possibly need to parse the errors related to validation of your model.  It uses attributes I placed on my Attendee class to do so.  As I mentioned before, attributes are used for UI validation as well as database design when you use EF Code First with ASP.NET MVC, which is pretty cool.  If data is saved, I am returning “OK.”  As you can see in my javascript above, I am looking for string “OK” and redirecting to the Index action/Url – list of attendees.  Alternatively, I could stay on the same page.  There is a lot of room for clean up on this page, of course.  I could add some animations to play during submit, disable all the controls, save newly created ID into a hidden field for subsequent updates, show error messages, maybe even replace entire Html of the form, replacing OK string with something like return View(attendee) or RenderPartial call.

Thank you.

Post to Twitter

Localizing / Customizing Entity Framework and ASP.NET MVC 3

In most demos that you see that involve entity framework code first and ASP.NET MVC 3, localization is not mentioned.  What if you want to make your data multi-language friendly?  Here is a simple example: I want to have title column to be at most 30 characters in my entity:

    [StringLength(30)]

    public string Title { get; set; }

 

If you run the form with this configuration and you enter more than 30 characters, you will get the following message: The field Title must be a string with a maximum length of 30.  This may be OK for some folks, but it does not follow proper English grammar.  So, let’s fix the problem.  First thing we need is create a resource file.  I typically put resources into its own assembly, so I am going to create new class library project, add new item of type Resource, and create new string key Title30Characters and appropriate value:

image

Now, let’s customize the attribute in the following manner:

    [StringLength(30,

      ErrorMessageResourceName = "Title30Characters",

      ErrorMessageResourceType = typeof(Resource))]

 

That is it.  One important thing to notice is that most attributes in Data Annotations namespace have the same two parameters used for localization: ErrorMessageResourceName and ErrorMessageResourceType.

 

    [StringLength(30,

      ErrorMessageResourceName = "Title30Characters",

      ErrorMessageResourceType = typeof(Resource))]

    [Required(

      ErrorMessageResourceName = "TitleRequired",

      ErrorMessageResourceType = typeof(Resource))]

    [Display(Name = "Title", ResourceType = typeof(Resource))]

    public string Title { get; set; }

 

Above you see the final version of the Title field attributes.  I am specifying maximum length, required field and display name, all coming from resources, specifically Resource class.  One interesting thing to notice is that I am using the same attributes to define messages in ASP.NET MVC and database structure.  Database does not care about messages I am adding to StringLength attribute, but it is using the value of 30 to define the size of the field.

Now, here is one more use case:  I want to handle parsing errors.  For example I have a Session Date field that maps to date time picker control in jQuery.  If I enter the following text 112121, here is what message will be generated:  The value ’112121′ is not valid for Session Date.  Not friendly.  Here is how I can also customize all error messages in ASP.NET MVC.  I can do it in Controller (Create or Update) method.  In the example below I am using Create method, testing for errors, and putting in custom error for Session Date property:

 

    public ActionResult Create()

    {

      var view = View(new Session());

      view.ViewBag.Action = "Create";

      return view;

    }

 

   

    [HttpPost]

    public ActionResult Create(Session session)

    {

      if (ModelState.IsValid)

      {

        db.Sessions.Add(session);

        db.SaveChanges();

        return RedirectToAction("Index");

      }

      else

      {

        if (ModelState["SessionDate"].Errors.Count == 1)

        {

          string date = ModelState["SessionDate"].Value.AttemptedValue;

          DateTime test;

          if (!DateTime.TryParse(date, out test))

          {

            ModelState["SessionDate"].Errors.Clear();

            ModelState["SessionDate"].Errors.Add(new ModelError(Resource.DateInvalidInvalidFormat));

          }

        }

      }

      var view = View(session);

      view.ViewBag.Action = "Create";

      return view;

    }

 

As you can see above, I am checking for errors in ModelState, removing default error only if my parsing fails on proposed value, and putting in custom message from resources.

 

Alternatively, you can use “buddy classes” or MetadataType attribute to define your metadata in a “buddy” class.  I personally do not like this approach, it feels awkward to me.

That is all there is to it.

Thanks.

Post to Twitter

More on Repository Pattern with Entity Framework Code First

I got a comment on my first post on this pattern that pointed out unnecessary use of reflection as well as a way to make my sample cleaner.  I took an opportunity to go ahead and update the sample.  I added a bit of new functionality to illustrate how you can also pass in where clause and order by clause usage.  I added a couple of functions to my base repository class to illustrate how to do this.  Here is the function that returns filtered and sorted data:

    /// <summary>

    /// Select data from database using a where clause

    /// </summary>

    /// <typeparam name="TItem">Type of data to select</typeparam>

    /// <param name="whereClause">Where clause / function</param>

    /// <param name="orderBy">Order by clause</param>

    /// <returns></returns>

    public IOrderedQueryable<TItem> Select<TItem>(

      Expression<Func<TItem, bool>> whereClause,

      Expression<Func<TItem, object>> orderBy)

       where TItem : class, new()

    {

      IOrderedQueryable<TItem> data = context.Set<TItem>().Where(whereClause).OrderBy(orderBy);

      return data;

    }

 

 

Here is how I would call this function:

        var activeOrderedProducts =

          repository.Select<Product>(one => one.IsActive, one => one.ProducName).ToList();

 

Pretty simple so far.  Now I am going to take it a step further and extract an interface from my repository.  Ideally, I would create an interface first, but this is an experiment.  Interface would look as follows:

using System;

using System.Linq.Expressions;

using System.Linq;

using System.Data.Entity;

using System.Data.Entity.Infrastructure;

namespace RepositoryEFCodeFirst

{

  public interface IEFRepository<TContext> : IDisposable

     where TContext : DbContext, IObjectContextAdapter, new()

  {

 

    void Delete<TItem>(TItem item) where TItem : class, new();

   

    TItem Insert<TItem>(TItem item) where TItem : class, new();

   

    IQueryable<TItem> Select<TItem>() where TItem : class, new();

   

    IQueryable<TItem> Select<TItem>(Expression<Func<TItem, bool>> whereClause) where TItem : class, new();

   

    IOrderedQueryable<TItem> Select<TItem>(Expression<Func<TItem, bool>> whereClause, Expression<Func<TItem, object>> orderBy)

      where TItem : class, new();

   

    TItem Update<TItem>(TItem item) where TItem : class, new();

  }

}

 

 

The last step would be to configure dependency injection and use an interface to resolve repository.  Ordinarily, you would configure unity container in global.asax file for example for WCF service or a web application.  Code would look as following:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using Microsoft.Practices.Unity;

 

namespace RepositoryEFCodeFirst

{

  class Program

  {

    static UnityContainer container = new UnityContainer();

 

    static void Main(string[] args)

    {

 

      container.RegisterType<IEFRepository<ProductContext>, EFRepository<ProductContext>>(

        new ContainerControlledLifetimeManager());

 

Now my code is even cleaner – I use interfaces everywhere and my “business code” does not deal with data access at all, considering that I would register my types elsewhere, not in my business layer.

Here is the final program code that uses repository:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using Microsoft.Practices.Unity;

 

namespace RepositoryEFCodeFirst

{

  class Program

  {

    static UnityContainer container = new UnityContainer();

 

    static void Main(string[] args)

    {

 

      container.RegisterType<IEFRepository<ProductContext>, EFRepository<ProductContext>>(

        new ContainerControlledLifetimeManager());

 

      using (var repository = container.Resolve<IEFRepository<ProductContext>>())

      {

        Console.WriteLine("Total products in DB : " +

            repository.Select<Product>().Count().ToString());

 

        Product newProduct = new Product();

        newProduct.ProducName = "Plates";

        newProduct.ProducNumber = "001";

        newProduct.Notes = "SOme notes for plates";

        newProduct.IsActive = true;

 

        newProduct = repository.Insert(newProduct);

 

        var ordered = repository.Select<Product>()

          .Where(one => one.IsActive == true)

          .OrderBy(one => one.ProducNumber).ToList();

 

        Console.WriteLine("New id is " + newProduct.ProductId.ToString());

 

 

        var aProduct = repository.Select<Product>().Where(one => one.IsActive).First();

 

        var activeProducts = repository.Select<Product>(one => one.IsActive).ToList();

 

        var activeOrderedProducts =

          repository.Select<Product>(one => one.IsActive, one => one.ProducName).ToList();

 

        aProduct.ProducName = "Updated Plates";

 

        aProduct = repository.Update(aProduct);

 

        aProduct = repository.Select<Product>()

          .Where(one => one.ProductId == newProduct.ProductId).First();

 

        Console.WriteLine("Update name is: " + aProduct.ProducName.ToString());

 

        repository.Delete(aProduct);

 

      }

    }

  }

}

 

I am also pasting in entire repository class (updated):

using System;

using System.Configuration;

using System.Data.Entity;

using System.Data.Entity.Infrastructure;

using System.Linq;

using System.Linq.Expressions;

using Microsoft.Practices.Unity;

 

namespace RepositoryEFCodeFirst

{

  /// <summary>

  /// Repository base class used with DbContext

  /// </summary>

  /// <typeparam name="TContext">Type of DdContext that this repository operates on</typeparam>

  public class EFRepository<TContext> : IDisposable, IEFRepository<TContext>

      where TContext : DbContext, IObjectContextAdapter, new()

  {

    private TContext context;

 

    /// <summary>

    /// Create new instance of repository

    /// </summary>

    /// <param name="connectionStringName">Connection string name from .config file</param>

    public EFRepository(string connectionStringName)

    {

      context = new TContext();

      context.Database.Connection.ConnectionString =

          ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString;

    }

 

    [InjectionConstructor]

    public EFRepository()

    {

      context = new TContext();

      context.Database.Connection.ConnectionString =

          ConfigurationManager.ConnectionStrings["ProductConnection"].ConnectionString;

    }

 

    /// <summary>

    /// Dispose repository

    /// </summary>

    public void Dispose()

    {

      if (context != null)

      {

        context.Dispose();

        context = null;

      }

    }

 

 

    /// <summary>

    /// Select data from database

    /// </summary>

    /// <typeparam name="TItem">Type of data to select</typeparam>

    /// <returns></returns>

    public IQueryable<TItem> Select<TItem>()

       where TItem : class, new()

    {

      DbSet<TItem> set = context.Set<TItem>();

      return set;

    }

 

    /// <summary>

    /// Select data from database using a where clause

    /// </summary>

    /// <typeparam name="TItem">Type of data to select</typeparam>

    /// <param name="whereClause">Where clause / function</param>

    /// <returns></returns>

    public IQueryable<TItem> Select<TItem>(Expression<Func<TItem, bool>> whereClause)

       where TItem : class, new()

    {

      IQueryable<TItem> data = context.Set<TItem>().Where(whereClause);

      return data;

    }

 

    /// <summary>

    /// Select data from database using a where clause

    /// </summary>

    /// <typeparam name="TItem">Type of data to select</typeparam>

    /// <param name="whereClause">Where clause / function</param>

    /// <param name="orderBy">Order by clause</param>

    /// <returns></returns>

    public IOrderedQueryable<TItem> Select<TItem>(

      Expression<Func<TItem, bool>> whereClause,

      Expression<Func<TItem, object>> orderBy)

       where TItem : class, new()

    {

      IOrderedQueryable<TItem> data = context.Set<TItem>().Where(whereClause).OrderBy(orderBy);

      return data;

    }

 

    /// <summary>

    /// Insert new item into database

    /// </summary>

    /// <typeparam name="TItem">Type of item to insert</typeparam>

    /// <param name="item">Item to insert</param>

    /// <returns>Inserted item</returns>

    public TItem Insert<TItem>(TItem item)

        where TItem : class, new()

    {

      DbSet<TItem> set = context.Set<TItem>();

      set.Add(item);

      context.SaveChanges();

      return item;

    }

 

    /// <summary>

    /// Update an item

    /// </summary>

    /// <typeparam name="TItem">Type of item to update</typeparam>

    /// <param name="item">Item to update</param>

    /// <returns>Updated item</returns>

    public TItem Update<TItem>(TItem item)

        where TItem : class, new()

    {

      DbSet<TItem> set = context.Set<TItem>();

      set.Attach(item);

      context.Entry(item).State = System.Data.EntityState.Modified;

      context.SaveChanges();

      return item;

    }

 

    /// <summary>

    /// Delete an item

    /// </summary>

    /// <typeparam name="TItem">Type of item to delete</typeparam>

    /// <param name="item">Item to delete</param>

    public void Delete<TItem>(TItem item)

       where TItem : class, new()

    {

      DbSet<TItem> set = context.Set<TItem>();

      var entry = context.Entry(item);

      if (entry != null)

      {

        entry.State = System.Data.EntityState.Deleted;

      }

      else

      {

        set.Attach(item);

      }

      context.Entry(item).State = System.Data.EntityState.Deleted;

      context.SaveChanges();

    }

 

  }

}

 

You can download entire solution here.

Post to Twitter

Technical Interview Questions and Answers

I recently read Scott Hanselman’s post on technical interviews.

I took a stab at answering those for my own amusement.  I took a bit of time to research the questions to ensure my answers are correct (as far as I know anyway).  So, I thought, why not post them and get some feedback?  Also, I often times put articles on my blog to help me have one site I can use as a quick reference for issues I encountered in my career..

  • What is Software Craftsmanship movement??

As aspiring Software Craftsmen we are raising the bar of professional software development by practicing it and helping others learn the craft. Through this work we have come to value:

· Not only working software, but also well-crafted software

· Not only responding to change, but also steadily adding value

· Not only individuals and interactions, but also a community of professionals

· Not only customer collaboration, but also productive partnerships

That is, in pursuit of the items on the left we have found the items on the right to be indispensable.

  • What are principles of OOP?
    • In traditional computer science courses those are encapsulation, inheritance and polymorphism.
      • Encapsulation
        • Restrict access to some implementation details, only expose public (consumable) methods. Ability to bundle methods and data into constructs (classes).
      • Inheritance
        • Reuse attributes and behavior of objects by basing classes on other classes.
      • Polymorphism
        • An ability to create function, object or variable that has more than one form / implementation. As a result different objects can respond to the same message in different way.
  • What is SOLID?
    • Single Responsibility Principle
      • The notion that an object should have only a single responsibility. As a result, an object will have a single reason to change, minimizing the maintenance efforts and limiting the impact of a change
    • Open/Close Principle
      • The notion that software entities should be open for extension, but closed for modification. The idea was that once completed, the implementation of a class could only be modified to correct errors; new or changed features would require that a different class be created. That class could reuse coding from the original class through inheritance. The derived subclass might or might not have the same interface as the original class.
    • Liskov Substitution Principle
      • The notion that objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program. If in a computer program if S is a subtype of T, then objects of type T may be replaced with objects of type S (i.e., objects of type S may be substitutes for objects of type T), without altering any of the desirable properties of that program
    • Interface Segregation Principle
      • The notion that many client specific interfaces are better than one general purpose interface. The idea is that once an interface becomes too large, it needs to be broken down into a group of smaller interfaces. The idea is that a client of an interface does not need to be exposed to methods that do not pertain to that client.
    • Dependency Inversion Principle
      • The notion that one should depend upon abstractions instead or concretions.
        • High-level modules should not depend on low-level modules. Both should depend on abstractions.
        • Abstractions should not depend upon details. Details should depend upon abstractions.
  • Why is the Single Responsibility Principle important?
    • If an object has a single reason to exists, it will only have a single reason to change. Change can be defined as the maintenance of the software, that takes much longer timeframe than the time to initially create the software. If we minimize the reason for change, we will minimize the maintenance costs as well as impacts of that change.
  • What is Inversion of Control? How does that relate to dependency injection?
    • In computer programming, Inversion of control (IoC) is an abstract principle describing an aspect of some software architecture designs in which the flow of control of a system is inverted in comparison to procedural programming. In traditional programming the flow of the business logic is controlled by a central piece of code, which calls reusable subroutines that perform specific functions. Using Inversion of Control this "central control" design principle is abandoned. The caller’s code deals with the program’s execution order, but the business knowledge is encapsulated by the called subroutines.
    • In practice, Inversion of Control is a style of software construction where reusable generic code controls the execution of problem-specific code. With this approach implementation is decoupled from execution. Ideally, each component of a system would depend on an interface that is implemented by another component. This promoted decoupling, single responsibility principle, and side effects of a change to a component.
    • Dependency injection is a technique that would allow a developer to indicate to a component what other components it can use. In this case we supply a dependency or a reference to a software component. Instead of hard-coding dependencies, a component supplies a list of dependencies it needs to a service/DI framework.
  • How does a 3 tier application differ from a 2 tier one?
    • Tiers refer to physical computer boundaries. Two tier applications will have a UI tier (client tier) and database tier. Three tier applications will typically have UI/client tier, application server (services) tier and database tier.
  • Why are interfaces important?
    • They minimize dependencies between objects by hiding implementation details that a component exposes from a consumer of that component. It allows for substitution of one component with another, without consumer changing any code. It serves directly to polymorphism principle of OOP.
  • What is the Repository pattern? The Factory Pattern? Why are patterns important?
    • Repository pattern typically refers to as dependency free access to data. In this case consumer of data only takes dependency on interfaces or POCO objects. It is important because it minimizes coupling and directly serves Dependency inversion principle.
    • Factory pattern refers to object creation without specifying exact class to be created. Typically they return interfaces.
  • What are some examples of anti-patterns?
    • Premature optimization
    • Code features you do not currently need
    • Copy/paste inheritance
  • Who are the Gang of Four? Why should you care?
    • The authors of the Design Patterns Book came to be known as the "Gang of Four." The name of the book is "Design Patterns: Elements of Reusable Object-Oriented Software", came to be known "book by the gang of four". After all, it isn’t the ONLY book on patterns. That got shortened to "GOF book", which is pretty cryptic the first time you hear it.
      • Erich Gamma
      • Richard Helm
      • Ralph Johnson
      • John Vlissides
    • Design patterns can speed up the development process by providing tested, proven development paradigms.

Please leave comments as you see fit.  I hope this will start a mutually beneficial conversion.

Post to Twitter

More on Markup Extensions in Silverlight 5

In my previous post I showed how to write a simple mark up extension.  I also noticed that not too many folks are aware of the fact that you can obtain a lot of information about how markup extension is used in XAML from the provider object.  I am going to demonstrate how to do this.  I will write an extension that would invoke a method on view model when a button is clicked by “binding” directly to Click event of the button.

Frist, we have to know more about the object we are using mark up extension on.  I am going to call mine EventToMethod.  Here is what the class looks like

using System;

using System.Reflection;

using System.Windows;

using System.Windows.Markup;

using System.Xaml;

 

namespace SL5Features.Extensions

{

  /// <summary>

  /// Extension that invokes a specified method when an event occurs.

  /// </summary>

  public class EventToMethod : FrameworkElement, IMarkupExtension<Delegate>

  {

    /// <summary>

    /// method handle that will be invoked

    /// </summary>

    private MethodInfo executeMethod = null;

 

    /// <summary>

    /// Main method required to be implemented by mark up extension

    /// </summary>

    /// <param name="serviceProvider">Service provider</param>

    /// <returns>Event delegate</returns>

    public Delegate ProvideValue(IServiceProvider serviceProvider)

    {

      // obtain value target provider and get mark up extension’s target from it

      var target =

        (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));

 

      // since we are bound to an event, we are getting EventInfo object

      EventInfo prop = target.TargetProperty as EventInfo;

      // test to see what type of event we are getting

      if (prop.EventHandlerType.Equals(typeof(RoutedEventHandler)))

      {

        // create delegate for routed event and return it

        return new RoutedEventHandler(RoutedHandler);

      }

      else

      {

        //create delegate for regular event and return it

        return new EventHandler(RegularHandler);

      }

    }

 

    /// <summary>

    /// Routed event handler delegate to invoke in response to routed event

    /// </summary>

    /// <param name="sender"></param>

    /// <param name="args"></param>

    public void RoutedHandler(object sender, RoutedEventArgs args)

    {

      RegularHandler(sender, args);

    }

 

    /// <summary>

    /// Event handler to invoke in response to plain vanilla event

    /// </summary>

    /// <param name="sender"></param>

    /// <param name="args"></param>

    public void RegularHandler(object sender, EventArgs args)

    {

      if (executeMethod == null)

      {

        Type type = ViewModel.GetType();

        executeMethod = type.GetMethod(MethodName);

      }

      executeMethod.Invoke(ViewModel, new object[] { });

    }

 

    /// <summary>

    /// Name of the method to invoke when an event is invoked, such as button click

    /// </summary>

    public string MethodName

    {

      get { return (string)GetValue(MethodNameProperty); }

      set { SetValue(MethodNameProperty, value); }

    }

    public static readonly DependencyProperty MethodNameProperty =

        DependencyProperty.Register(

        "MethodName",

        typeof(string),

        typeof(EventToMethod),

        new PropertyMetadata(null));

 

    /// <summary>

    /// View model to invoke

    /// </summary>

    public Object ViewModel

    {

      get { return (Object)GetValue(ViewModelProperty); }

      set { SetValue(ViewModelProperty, value); }

    }

 

    public static readonly DependencyProperty ViewModelProperty =

        DependencyProperty.Register(

        "ViewModel", typeof(Object),

        typeof(EventToMethod),

        new PropertyMetadata(null));

 

  }

}

 

I documented properties, etc…  The basic idea is to get button (or any other) object from the provider, get event information, then create a delegate for that event and return it, just like any other mark up extension must return a value.  I added ViewModel and MethodName properties so that I can get event handle from ViewModel based on event name.  If you bind your mark up extension to a property on a control, TargetProperty will contain PropertyInfo object.

XAML could not look simpler:

 

<ResourceDictionary

   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   xmlns:models="clr-namespace:SL5Features.Models"

   xmlns:ext="clr-namespace:SL5Features.Extensions">

 

  <DataTemplate DataType="models:Person">

    <Grid>

      <Grid.RowDefinitions>

        <RowDefinition Height="Auto"/>

        <RowDefinition Height="7"/>

        <RowDefinition Height="Auto"/>

        <RowDefinition Height="7"/>

        <RowDefinition Height="Auto"/>

      </Grid.RowDefinitions>

      <Grid.ColumnDefinitions>

        <ColumnDefinition Width="Auto"/>

        <ColumnDefinition Width="7"/>

        <ColumnDefinition Width="*"/>

      </Grid.ColumnDefinitions>

     

      <TextBlock Text="First Name:" 

                Grid.Column="0" Grid.Row="0" 

                HorizontalAlignment="Right"

                VerticalAlignment="Center"

                Foreground="Red"/>

     

      <TextBlock Text="Last Name:" 

                Grid.Column="0" Grid.Row="2" 

                HorizontalAlignment="Right"

                VerticalAlignment="Center"

                Foreground="Red"/>

     

      <TextBox Text="{Binding Path=FirstName, Mode=TwoWay}"

              Grid.Column="2" Grid.Row="0"

              Background="Yellow"/>

     

      <TextBox Text="{Binding Path=LastName, Mode=TwoWay}" 

              Grid.Column="2" Grid.Row="2"

              Background="Yellow"/>

 

      <Button Content="Save" HorizontalAlignment="Left" 

             Grid.Row="4" Grid.Column="0"

             Click="{ext:EventToMethod 

                 ViewModel={Binding ElementName=LayoutRoot, Path=DataContext}, 

                 MethodName=RunIt}"/>

    </Grid>

  </DataTemplate>

</ResourceDictionary>

 

As you can see, I am binding button’s click method via my mark up extension.  Now, in my view model I just need to declare RunIt method, and that is it:

using SL5Features.Models;

using System.Windows;

 

namespace SL5Features.ViewModels

{

  public class PersonViewModel : ViewModelBase<Person>

  {

    public PersonViewModel()

    {

      Model = new Person() { FirstName = "Sergey", LastName = "Barskiy" };

    }

 

    public void Run(object parameter)

    {

      MessageBox.Show("Run");

    }

 

    public void RunIt()

    {

      MessageBox.Show("RunIt");

    }

 

    public bool CanRun(object parameter)

    {

      return true;

    }

  }

}

 

I added all the functionality to the solution from the previous post, but I am using alternate template for this implementation.  Too see the end result, just add ?Template=Alt to the query string when you run the app. 

To summarize, the idea is the same as my previous post – eliminate the need to create commands in my view model.

 

You can download updated solution here.

Thanks.

Post to Twitter

Markup Extensions in Silverlight 5

Another cool feature available in Silverlight 5 is markup extensions.  The idea behind the feature is ability to allow developers to supply values to XAML parser at the time it parses visual tree.  In other words, once parser finds a markup extension in XAML, it will create an instance of it, set any properties that the extension might have, then call ProvideValue method that will return a value of the type that the property that markup extension supports expects.  For example, I am writing a markup extension to supply an ICommand to the button, my XAML would looks like the following:

      <Button Content="Save" HorizontalAlignment="Left" 

             Grid.Row="4" Grid.Column="0"

             Command="{ext:CommandMarkupExtension 

                 ViewModel={Binding ElementName=LayoutRoot, Path=DataContext}, 

                 ExecuteMethodName=Run, 

                 CanExecuteMethodName=CanRun}"/>

 

So, in this example for markup extension I am writing a command extension.  As you can see in the XAML above, my extension takes three parameters: ViewModel to invoke, execute and can execute method names.  This way I can de-clutter my view model by removing all the command instantiation code, and just write the two methods I need.  The code in this extension is very easy – just a handful of dependency properties and interface implementation for IMarkupExtension:

using System;

using System.Windows;

using System.Windows.Input;

using System.Xaml;

 

namespace SL5Features.Extensions

{

  public class CommandMarkupExtension : FrameworkElement, IMarkupExtension<ICommand>

  {

 

    public Object ViewModel

    {

      get { return (Object)GetValue(ViewModelProperty); }

      set { SetValue(ViewModelProperty, value); }

    }

 

    public static readonly DependencyProperty ViewModelProperty =

        DependencyProperty.Register(

        "ViewModel", typeof(Object),

        typeof(CommandMarkupExtension),

        new PropertyMetadata(null));

 

    public string ExecuteMethodName

    {

      get { return (string)GetValue(ExecuteMethodNameProperty); }

      set { SetValue(ExecuteMethodNameProperty, value); }

    }

    public static readonly DependencyProperty ExecuteMethodNameProperty =

        DependencyProperty.Register(

        "ExecuteMethodName",

        typeof(string),

        typeof(CommandMarkupExtension),

        new PropertyMetadata(null));

 

 

 

    public string CanExecuteMethodName

    {

      get { return (string)GetValue(CanExecuteMethodNameProperty); }

      set { SetValue(CanExecuteMethodNameProperty, value); }

    }

 

    public static readonly DependencyProperty CanExecuteMethodNameProperty =

        DependencyProperty.Register(

        "CanExecuteMethodName",

        typeof(string),

        typeof(CommandMarkupExtension),

        new PropertyMetadata(null));

 

    public ICommand ProvideValue(IServiceProvider serviceProvider)

    {

      ReflectionCommand command =

        new ReflectionCommand(ViewModel, ExecuteMethodName, CanExecuteMethodName);

      return command;

    }

  }

}

 

To support the extension I need to write a command object that would actually implement ICommand.  This class is pretty trivial, so I am not commenting it much:

using System;

using System.Reflection;

using System.Windows;

using System.Windows.Input;

 

namespace SL5Features.Extensions

{

  public class ReflectionCommand : ICommand

  {

 

    private MethodInfo canExecuteMethod = null;

    private MethodInfo executeMethod = null;

    private object viewModel = null;

 

    private ReflectionCommand() { }

 

    public ReflectionCommand(

      object viewModel,

      string executeMethodName,

      string canExecuteMethodName)

    {

      this.viewModel = viewModel;

      Type type = viewModel.GetType();

      if (!string.IsNullOrEmpty(canExecuteMethodName))

      {

        this.canExecuteMethod = type.GetMethod(canExecuteMethodName);

      }

      this.executeMethod = type.GetMethod(executeMethodName);

 

    }

 

    public void Execute(object parameter)

    {

      executeMethod.Invoke(viewModel, new[] { parameter });

    }

 

    public bool CanExecute(object parameter)

    {

      if (viewModel != null && canExecuteMethod != null)

      {

        return (bool)canExecuteMethod.Invoke(viewModel, new[] { parameter });

      }

      else

      {

        return true;

      }

    }

 

 

    public event EventHandler CanExecuteChanged;

 

    public void RaiseCanExecuteChanged()

    {

      if (CanExecuteChanged != null)

      {

        CanExecuteChanged(this, EventArgs.Empty);

      }

    }

 

 

  }

}

 

So, far it is pretty easy.  Now, all I have to do is add Run and CanRun method on my view model that my command will invoke:

using SL5Features.Models;

using System.Windows;

 

namespace SL5Features.ViewModels

{

  public class PersonViewModel : ViewModelBase<Person>

  {

    public PersonViewModel()

    {

      Model = new Person() { FirstName = "Sergey", LastName = "Barskiy" };

    }

 

    public void Run(object parameter)

    {

      MessageBox.Show("Run");

    }

    public bool CanRun(object parameter)

    {

      return true;

    }

  }

}

 

Hopefully, I demonstrated the power of markup extension for you.  The goal of using them to me is reduction of the amount of code elsewhere in the system, since you will obviously have to write more XAML.  Of course, I am sure Blend 5 will support mark up extensions, so potentially you can just drag my extension on top of the button and setup a few properties in properties window.  You will also see a number of demos where an extension is used to support localization, which seems pretty intuitive use of the feature. Bottom line is: I love getting new features that make my job easier by allowing me to write less code and re-use more of the code written.

 

You can download the example here.

Thanks.

Post to Twitter

Unleash the Power of Implicit Data Templates in Silverlight 5

One of the cool new features in Silverlight 5 are implicit data templates.  They allow developers to associate a set of visuals encapsulated inside a data template with a specific class.  You can find a cool demo of this feature on Tim Heuer;s blog.  One of the links in this article shows how to use the feature inside a list box.

I would like to demonstrate ultimate power of this feature when it comes to creating views dynamically based on a specific type.  Let me elaborate.  I want to create an entry screen for a person class using MVVM pattern.  First, I am creating a simple Person class:

 

 

namespace SL5Features.Models

{

  public class Person : ModelBase

  {

 

    private string firstName;

 

    public string FirstName

    {

      get { return firstName; }

      set { firstName = value; OnPropertyChanged("FirstName"); }

    }

 

    private string lastName;

 

    public string LastName

    {

      get { return lastName; }

      set { lastName = value; OnPropertyChanged("LastName"); }

    }

 

  }

}

 

My base class does nothing more than implements INotifyPropertyChanged interface:

using System.ComponentModel;

 

namespace SL5Features.Models

{

  public class ModelBase : INotifyPropertyChanged

  {

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)

    {

      if (PropertyChanged != null)

      {

        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

      }

    }

  }

}

 

Now, I want to create a default template for this class.  Unlike other demos you saw so far, I am going to add this template to a resource dictionary.  I am going to create a new folder in my project called Templates.  Then, I am going to right-click, select Add New Item, then select resource dictionary type.  Once dictionary is created, I am going to add a data template to it, and associate it with the person type.  I have to add namespace to my models of course.  Here is what my dictionary looks like:

<ResourceDictionary

   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   xmlns:models="clr-namespace:SL5Features.Models">

 

  <DataTemplate DataType="models:Person">

    <Grid>

      <Grid.RowDefinitions>

        <RowDefinition Height="Auto"/>

        <RowDefinition Height="7"/>

        <RowDefinition Height="Auto"/>

      </Grid.RowDefinitions>

      <Grid.ColumnDefinitions>

        <ColumnDefinition Width="Auto"/>

        <ColumnDefinition Width="7"/>

        <ColumnDefinition Width="*"/>

      </Grid.ColumnDefinitions>

     

      <TextBlock Text="First Name:" 

                Grid.Column="0" Grid.Row="0" 

                HorizontalAlignment="Right"

                VerticalAlignment="Center"/>

     

      <TextBlock Text="Last Name:" 

                Grid.Column="0" Grid.Row="2" 

                HorizontalAlignment="Right"

                VerticalAlignment="Center"/>

     

      <TextBox Text="{Binding Path=FirstName, Mode=TwoWay}"

              Grid.Column="2" Grid.Row="0"/>

     

      <TextBox Text="{Binding Path=LastName, Mode=TwoWay}" 

              Grid.Column="2" Grid.Row="2"/>

    </Grid>

  </DataTemplate>

</ResourceDictionary>

 

Pretty simple screen.  Now for giggles I am going to create new dictionary with slightly different implementation for the same UI:

<ResourceDictionary

   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   xmlns:models="clr-namespace:SL5Features.Models">

 

  <DataTemplate DataType="models:Person">

    <Grid>

      <Grid.RowDefinitions>

        <RowDefinition Height="Auto"/>

        <RowDefinition Height="7"/>

        <RowDefinition Height="Auto"/>

      </Grid.RowDefinitions>

      <Grid.ColumnDefinitions>

        <ColumnDefinition Width="Auto"/>

        <ColumnDefinition Width="7"/>

        <ColumnDefinition Width="*"/>

      </Grid.ColumnDefinitions>

     

      <TextBlock Text="First Name:" 

                Grid.Column="0" Grid.Row="0" 

                HorizontalAlignment="Right"

                VerticalAlignment="Center"

                Foreground="Red"/>

     

      <TextBlock Text="Last Name:" 

                Grid.Column="0" Grid.Row="2" 

                HorizontalAlignment="Right"

                VerticalAlignment="Center"

                Foreground="Red"/>

     

      <TextBox Text="{Binding Path=FirstName, Mode=TwoWay}"

              Grid.Column="2" Grid.Row="0"

              Background="Yellow"/>

     

      <TextBox Text="{Binding Path=LastName, Mode=TwoWay}" 

              Grid.Column="2" Grid.Row="2"

              Background="Yellow"/>

    </Grid>

  </DataTemplate>

</ResourceDictionary>

 

Now, the fun part of injecting the visuals into my view.  I am going to inject them into MainPage, but ordinarily you would create a new user control.  All I do is add ContentControl and set Content to my view model’s property called Model that will contain my Person instance:

<UserControl 

   x:Class="SL5Features.MainPage"

   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

   xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

   xmlns:models="clr-namespace:SL5Features.Models"

   mc:Ignorable="d"

   d:DesignHeight="300" d:DesignWidth="400">

 

  <Grid x:Name="LayoutRoot">

    <ContentControl 

     x:Name="Host" 

     HorizontalAlignment="Stretch" 

     VerticalAlignment="Stretch" 

     HorizontalContentAlignment="Stretch" 

     VerticalContentAlignment="Stretch"

     Content="{Binding Path=Model}"

     />

  </Grid>

</UserControl>

 

Oh, I did not show you my view models structure.  I have a base class with Model property and INotifyPropertyChanged implementation.  Simple and basic:

using System.ComponentModel;

 

namespace SL5Features.ViewModels

{

  public class ViewModelBase<T> : INotifyPropertyChanged

  {

 

    private T model;

    public T Model

    {

      get { return model; }

      set { model = value; OnPropertyChanged("Model"); }

    }

 

 

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)

    {

      if (PropertyChanged != null)

      {

        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

      }

    }

  }

}

 

In my person view model I am going to cheat and just create an instance of a person:

using SL5Features.Models;

 

namespace SL5Features.ViewModels

{

  public class PersonViewModel : ViewModelBase<Person>

  {

    public PersonViewModel()

    {

      Model = new Person() { FirstName = "Sergey", LastName = "Barskiy" };

    }

  }

}

 

Now, in App.Xaml.cs I am going to inject the view model into my main page:

    private void Application_Startup(object sender, StartupEventArgs e)

    {

      AddDictionaries();

      this.RootVisual = new MainPage() { DataContext = new PersonViewModel() };

    }

 

Now, if you run the application you will not get the desired result.  Last step is to show you what magic my AddDictionaries contains:

 

    private void AddDictionaries()

    {

      // do we have a template query parameter

      var hasTempalteKey = HtmlPage.Document.QueryString.ContainsKey("Template");

      // create Url for default visuals dictionary

      var uri = new Uri("/SL5Features;component/Templates/Templates.xaml", UriKind.Relative);

 

      // now if I have query parameter called Template set to "ALT", I am going to use differnt Url

      if (hasTempalteKey && HtmlPage.Document.QueryString["Template"].ToUpper().Contains("ALT"))

      {

        // alternate tempalte Url

        uri = new Uri("/SL5Features;component/Templates/AltTemplates.xaml", UriKind.Relative);

      }

      // now creat new dictionary and inject it into Application resources

      ResourceDictionary dictionary = new ResourceDictionary();

      dictionary.MergedDictionaries.Add(

        new ResourceDictionary() { Source = uri });

      this.Resources.MergedDictionaries.Add(dictionary);

    }

 

I commented the code to demonstrate what I am doing.  What my goal is to swap visuals based on query string containing Template=Alt.  Now, run the application .  Here is what it looks like:

 

image

Now, the cool part.  Just alter the Url and whatch the magic:

image

As you can see, I have swapped the visuals by dynamically swapping templates.  You can imagine that you can design template and use then as a replacement for your views, injecting them into pre-defined shells.  You can see how you can decrease the amount of code needed for view / view model construction in a typical MVVM application, but also dynamically inject different visuals without changing any code.

You can download my sample application here.

Enjoy Silverlight 5!  You can find the download links here.

Post to Twitter

Do You Want to Learn More About Azure?

clip_image002

Microsoft and Magenic want to show you the best way to include cloud computing into your technology solution set. Dan Sandlin (Azure Solution Specialist) will discuss which projects are right for cloud computing and which ones you should avoid, as well as how to select your first cloud project and the ROI of Azure. Sergey Barskiy (Magenic Principal Consultant) will discuss how cloud is more than just an enormous virtual machine and the building blocks of Azure.

Windows Azure offers flexibility, growth opportunities and long term stability, but only when approached the right way. Come learn where to start.

We will gather at the Ravinia Club in Atlanta on Thursday, April 21 from 7:30-10:30 am. Breakfast will be served.

clip_image004

clip_image002[4]

 

Event Details

Date:
Thursday, April 21
7:30-10:30am
Location:
2 Ravinia Drive #100
Atlanta, GA 30346

clip_image008

View Map on Bing

Get Directions

clip_image010

Post to Twitter

More on EF 4.1 Conventions

I got a comment today on my previous post that nullable types do not function as well.  Being a nice person that I am, I just added nullable support to sample project.

You can download update here.

Thanks.

Post to Twitter

Global Conventions in Entity Framework Code First v 4.1

In my previous post I showed how to implement custom conventions in absence of the same feature in Entity Framework 4.1.  Today I am going to expand on the same topic and try to create some global contentions.

Let me elaborate a bit on a problem I am trying to resolve.  For example, if I create a property of type decimal on a class that is used to create a set of entities in DbContext, it would result in the decimal(18,2) column definition in the database.  What if I would like my default to be (8,4) unless specified otherwise?  You can see my problem.  If I have 100 tables in my database all with 10 decimal fields, I would have to type in 1000 decimal column definitions using fluent API.   This is way too much typing to my taste. 

Here is the solution I would like to purse.  I am going to expand on my previous attribute based conventions and create a global, attribute-less convention.

First I am going to refactor my previous code and convert attribute specific conventions to generic conventions based on IConvention

Here is my new code to process all conventions and add one convention:

        /// <summary>

        /// Add one convention

        /// </summary>

        /// <param name="convention">Convention to add</param>

        protected void AddConvention(IConvention convention)

        {

            conventions.Add(convention);

        }

 

        /// <summary>

        /// Process conventions

        /// </summary>

        /// <param name="modelBuilder">Model builder</param>

        protected virtual void ProcessAddedConventions(DbModelBuilder modelBuilder)

        {

            if (conventions.Count > 0)

            {

                // poulate reflection data

                PopulateSetMetadata();

                // run through all added conventions

                conventions.ForEach(convention =>

                {

                    if (convention is IAttributeConvention)

                    {

                        ProcessAttributeBasedConvention(modelBuilder, convention as IAttributeConvention);

                    }

                   

                });

            }

        }

 

Now, I am going to write a new method to process global conventions.  I am going to extensively comment the code below:

    /// <summary>

    /// Process global conventions

    /// </summary>

    /// <param name="modelBuilder">Model builder</param>

    /// <param name="convention">One global convention to process</param>

    private void ProcessGlobalConvention(DbModelBuilder modelBuilder, IGlobalConvention convention)

    {

      var setMetadata = dbSetMetadata[this.GetType().AssemblyQualifiedName];

      // run through DbSets in current context

      setMetadata.ForEach(set =>

      {

        //run through properties in each DbSet<T> for class of type T

        set.DbSetItemProperties.ToList().ForEach(prop =>

        {

          // get type of property that matches current convention

          Type targetType = GetMatchingTypeForConfiguration(convention.PropertyConfigurationType);

          // make sure this type matched property type

          if (prop.PropertyInfo.PropertyType == targetType)

          {

            // Get entity method in ModuleBuilder

            // we are trying to get to the point of expressing the following

            //modelBuilder.Entity<Person>().Property(a => a.Name).IsMaxLength() for example

            var setMethod = modelBuilder.GetType()

                .GetMethod("Entity", BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy);

            // one we have Entity method, we have to add generic parameters to get to Entity<T>

            var genericSetMethod = setMethod.MakeGenericMethod(new Type[] { set.ItemType });

            // Get an instance of EntityTypeConfiguration<T>

            var entityInstance = genericSetMethod.Invoke(modelBuilder, null);

 

            //Get methods of EntityTypeConfiguration<T>

            var propertyAccessors = entityInstance.GetType().GetMethods(

                BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy).ToList();

 

            // we are looking for Property method that returns PropertyConfiguration

            // that is used in current convention

            var propertyMethod =

                propertyAccessors.Where(oneProperty =>

                    oneProperty.ReturnType == convention.PropertyConfigurationType).FirstOrDefault();

 

            //Get method handle in order to build the expression

            // example: (a => a.Name)

            var expressionGetMethod = GetPropertyExpressionMethodHandle();

 

            //Create lamda expression by making expression method that takes two generic parameters

            // one for class, the other for property type

            var genericExpressionMethod = expressionGetMethod

                .MakeGenericMethod(new Type[] { prop.PropertyInfo.DeclaringType, prop.PropertyInfo.PropertyType });

 

            //FInally, get lamda expression it self

            // example: (a => a.Name)

            var propertyExpression = genericExpressionMethod.Invoke(null, new object[] { prop.PropertyInfo });

 

            //Not get an instance of PrimitivePropertyConfiguration by 
            // infoking EntityTypeConfiguration<T>’s

            // Property() method

            var config = propertyMethod

                .Invoke(entityInstance, new object[] { propertyExpression }) as PrimitivePropertyConfiguration;

 

            //Finally, pass this configuration and attribute into the convention

            convention.ApplyConfiguration(prop.PropertyInfo, config);

          }

        });

      });

    }

 

Just like in attribute based convention method, I am running through all the properties for all the entities.  However, first step I am doing is making sure that the convention I am applying is matching the property type.  I am using the following method to get property type based on convention.

    /// <summary>

    /// Determine what property type should be used for a specific convention

    /// </summary>

    /// <param name="propertyConfigurationType">

    /// Type of PrimitivePropertyConfiguration to process

    /// </param>

    /// <returns>

    /// Property type that should be used with current convention

    /// </returns>

    private Type GetMatchingTypeForConfiguration(Type propertyConfigurationType)

    {

      if (propertyConfigurationType == typeof(DecimalPropertyConfiguration))

      {

        return typeof(decimal);

      }

      if (propertyConfigurationType == typeof(StringPropertyConfiguration))

      {

        return typeof(string);

      }

      if (propertyConfigurationType == typeof(DateTimePropertyConfiguration))

      {

        return typeof(DateTime);

      }

      if (propertyConfigurationType == typeof(BinaryPropertyConfiguration))

      {

        return typeof(byte[]);

      }

      else

      {

        return typeof(object);

      }

    }

 

For example, I only want to apply string based configuration to string properties.  The rest of the code on apply global conventions methods is just reflection code aimed to obtain property configuration and call Apply method of the global convention.  Here is a sample implementation for this convention, making all decimal properties decimal(8,4):

using System;

using System.Data.Entity.ModelConfiguration.Configuration;

using System.Reflection;

using EFCodeFirstConventions;

 

namespace EFCodeFirstConventionsConsole

{

  public class GenericDecimalConvention :

    GlobalConfigurationConvention<MemberInfo, DecimalPropertyConfiguration>

  {

    protected override void Apply(

      MemberInfo memberInfo,

      DecimalPropertyConfiguration propertyConfiguration)

    {

      propertyConfiguration.HasPrecision(8, 4);

    }

  }

}

 

If I add this convention to my extended context, I will make my decimals size (8,4) unless specified otherwise.  In order to do so, I am processing global conventions prior to attribute based conventions:

    /// <summary>

    /// Process conventions

    /// </summary>

    /// <param name="modelBuilder">Model builder</param>

    protected virtual void ProcessAddedConventions(DbModelBuilder modelBuilder)

    {

      if (conventions.Count > 0)

      {

        // poulate reflection data

        PopulateSetMetadata();

        // run through all global added conventions

        conventions.ForEach(convention =>

        {

          if (convention is IGlobalConvention)

          {

            ProcessGlobalConvention(modelBuilder, convention as IGlobalConvention);

          }

        });

        // run through attribute based conventions

        conventions.ForEach(convention =>

        {

          if (convention is IAttributeConvention)

          {

            ProcessAttributeBasedConvention(modelBuilder, convention as IAttributeConvention);

          }

        });

      }

    }

 

Now, let’s do another convention that is based on property names.  For example, I want to have all properties that have word Percent in them to be set as decimal(4,2).  I am just going to write a global convention for that:

using System.Data.Entity.ModelConfiguration.Configuration;

using System.Reflection;

using EFCodeFirstConventions;

 

namespace EFCodeFirstConventionsConsole

{

  public class PercentConvention :

    GlobalConfigurationConvention<MemberInfo, DecimalPropertyConfiguration>

  {

    protected override void Apply(

      MemberInfo memberInfo,

      DecimalPropertyConfiguration propertyConfiguration)

    {

      if (memberInfo.Name.ToUpper().Contains("PERCENT"))

      {

        propertyConfiguration.HasPrecision(4, 2);

      }

    }

  }

}

 

 

Super easy, now that I have my framework setup.  In this convention I am using the fact that I have MethodInfo as a parameter, so I can apply name based global conventions!  This cuts down on amount of fluent API code I have to write tremendously.  One thing to remember, I have to add conventions to my extended context in certain order to ensure they do not overwrite each other.

 

    public class CustomContext : ExtendedDbContext

    {

      public IDbSet<Person> Perosns { get; set; }

 

      protected override void AddConventions()

      {

        AddConvention(new EtendedStringConvention());

        AddConvention(new GenericDecimalConvention());

        AddConvention(new PercentConvention());

      }

 

    }

 

Here is my test Person class I am using:

using System.ComponentModel.DataAnnotations;

 

namespace EFCodeFirstConventionsConsole

{

  public class Person

  {

    [Key]

    public int PersonID { get; set; }

 

    [ExtendedString(10, 200, false)]

    public string Name { get; set; }

 

    public bool IsActive { get; set; }

 

    public decimal GenericDecimal { get; set; }

 

    public decimal Percent { get; set; }

  }

}

 

You can download updated project here.

 

Thank you.

Post to Twitter

Custom Conventions in Entity Framework Code First v 4.1

As you know, in preview version of Entity Framework code first existed concept of custom pluggable conventions that would allow the developer to avoid using large amounts of code in OnModelCreating method.  Typically, if one would like to keep entity classes free of entity framework references and possibly of Data Annotations references, fluent API available in ModelBuilder class can be used to configure entire model.  However, if you have reasonably large model, you will end up with thousands of lined of code in OnModelCreating  method of you custom DbContext.

Custom conventions would allow you to avoid this situation.  You would combine custom attributes with pluggable conventions that would pass the attribute value into your convention along with appropriate instance PropertyConfiguration, such as StringPropertyConfiguration.

Unfortunately, this functionality was removed from release candidate build and also will not be available in final build of EF 4.1 sometimes later this year.  I heard some complaints regarding this issue, and decided to write something compatible.

In this post I will describe how I went about this process, illustrating how to support primitive properties, such as string properties. 

I borrowed the concept from CTP 5.  My base class of custom convention is very similar to Microsoft one.

I started with the following interface:

using System;

using System.Data.Entity.ModelConfiguration.Configuration;

using System.Data.Entity.ModelConfiguration.Conventions;

using System.Reflection;

 

namespace EFCodeFirstConventions

{

    public interface IAttributeConvention : IConvention

    {

        void ApplyConfiguration(

            MemberInfo memberInfo,

            PrimitivePropertyConfiguration propertyConfiguration,

            Attribute attrribute);

 

        Type PropertyConfigurationType { get; }

        Type AttributeType { get; }

    }

}

 

 

IConvention class still exists in release candidate.  The idea behind the interface is as following.  I will call ApplyConfiguration method, passing the instance of attribute that my property inside entity class is decorated with along with PropertyInfo object (to provide additional information to the convention class).  Here is my implementation in an abstract class:

using System;

using System.Data.Entity.ModelConfiguration.Configuration;

using System.Reflection;

 

namespace EFCodeFirstConventions

{

    public abstract class AttributeConfigurationConvention<TMemberInfo, TPropertyConfiguration, TAttribute>

        : IAttributeConvention

        where TMemberInfo : MemberInfo

        where TPropertyConfiguration : PrimitivePropertyConfiguration

        where TAttribute : Attribute

    {

 

        public void ApplyConfiguration(

            MemberInfo memberInfo,

            PrimitivePropertyConfiguration propertyConfiguration,

            Attribute attribute)

        {

            Apply((TMemberInfo)memberInfo, (TPropertyConfiguration)propertyConfiguration, (TAttribute)attribute);

        }

 

        protected abstract void Apply(

            TMemberInfo memberInfo,

            TPropertyConfiguration propertyConfiguration,

            TAttribute attrribute);

 

 

        public Type PropertyConfigurationType

        {

            get { return typeof(TPropertyConfiguration); }

        }

 

        public Type AttributeType

        {

            get { return typeof(TAttribute); }

        }

 

    }

 

 

 

}

 

I introduced Apply method in my base convention class in order to make cleaner, strongly typed API in derived classes.  I also make convention strongly typed via generics, again in order to easy the pain of implementation.

Here is a sample implementation:

using System.Data.Entity.ModelConfiguration.Configuration;

using System.Reflection;

using EFCodeFirstConventions;

 

namespace EFCodeFirstConventionsConsole

{

    public class EtendedStringConvention :

        AttributeConfigurationConvention<MemberInfo, StringPropertyConfiguration, ExtendedStringAttribute>

    {

 

        protected override void Apply(

            MemberInfo memberInfo,

            StringPropertyConfiguration propertyConfiguration,

            ExtendedStringAttribute attrribute)

        {

            propertyConfiguration.IsUnicode(attrribute.IsUnicode);

            if (attrribute.MaxLength == int.MaxValue || attrribute.MaxLength == -1)

            {

                propertyConfiguration.IsMaxLength();

            }

            else if (attrribute.MaxLength == attrribute.MinLength && attrribute.MinLength > 0)

            {

                propertyConfiguration.IsMaxLength();

                propertyConfiguration.IsFixedLength();

                propertyConfiguration.HasMaxLength(attrribute.MaxLength);

            }

            else

            {

                propertyConfiguration.HasMaxLength(attrribute.MaxLength);

            }

        }

    }

}

 

 

As you can see, once you are in your Apply method if you have clean code that allows you to configure StringPropertyConfiguration based on ExtendedStringAttribute value.

using System;

 

namespace EFCodeFirstConventionsConsole

{

    [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]

    public class ExtendedStringAttribute : Attribute

    {

        public ExtendedStringAttribute()

            : this(isUnicode: true)

        {

 

        }

 

        public ExtendedStringAttribute(

            int minLength = 0, int maxLength = int.MaxValue, bool isUnicode = true)

        {

            MinLength = minLength;

            MaxLength = maxLength;

            IsUnicode = isUnicode;

        }

 

        public int MinLength { get; private set; }

        public int MaxLength { get; private set; }

        public bool IsUnicode { get; private set; }

    }

}

 

Code above is my attribute.  I am using it as follows:

using System.ComponentModel.DataAnnotations;

 

namespace EFCodeFirstConventionsConsole

{

    public class Person

    {

        [Key]

        public int PersonID { get; set; }

 

        [ExtendedString(10, 200, false)]

 

        public string Name { get; set; }

 

        public bool IsActive { get; set; }

 

    }

}

 

Easy as pie.  Now, here is the ugly code with plenty of reflection that supports this nice feature.  I documented the class itself very thoroughly to ensure that one can understand what I wrote.

using System;

using System.Collections.Generic;

using System.Data.Entity;

using System.Data.Entity.ModelConfiguration.Configuration;

using System.Linq;

using System.Linq.Expressions;

using System.Reflection;

using EFCodeFirstConventions.Reflection;

 

namespace EFCodeFirstConventions

{

    public abstract class ExtendedDbContext : DbContext

    {

        protected override void OnModelCreating(DbModelBuilder modelBuilder)

        {

            base.OnModelCreating(modelBuilder);

            // call derived class to add conventions

            AddConventions();

            // now process conventions

            ProcessAddedConventions(modelBuilder);

        }

 

        /// <summary>

        /// Force implementation via astract class

        /// </summary>

        protected abstract void AddConventions();

 

        // conventsions saved here

        private List<IAttributeConvention> conventions = new List<IAttributeConvention>();

 

        //reflrecion data about DbContext, its sets, properties and attributes

        private static Dictionary<string, List<DbSetMetadata>> dbSetMetadata =

            new Dictionary<string, List<DbSetMetadata>>();

 

        private static object locker = new object();

 

        /// <summary>

        /// Add one convention

        /// </summary>

        /// <param name="convention">Convention to add</param>

        protected void AddConvention(IAttributeConvention convention)

        {

            conventions.Add(convention);

        }

 

        /// <summary>

        /// Process conventions

        /// </summary>

        /// <param name="modelBuilder">Model builder</param>

        protected virtual void ProcessAddedConventions(DbModelBuilder modelBuilder)

        {

            if (conventions.Count > 0)

            {

                // poulate reflection data

                PopulateSetMetadata();

                // run through all added conventions

                conventions.ForEach(convention =>

                {

                    var setMetadata = dbSetMetadata[this.GetType().AssemblyQualifiedName];

                    // run through DbSets in current context

                    setMetadata.ForEach(set =>

                        {

                            //run through properties in each DbSet<T> for class of type T

                            set.DbSetItemProperties.ToList().ForEach(prop =>

                                {

                                    // get attribute that matches convention

                                    var data = prop.DbSetItemAttributes

                                        .Where(attr => attr.Attribute.GetType() == convention.AttributeType).FirstOrDefault();

 

                                    // this class’s property has the attribute

                                    if (data != null)

                                    {

                                        // Get entity method in ModuleBuilder

                                        // we are trying to get to the point of expressing the following

                                        //modelBuilder.Entity<Person>().Property
                                        // (a => a.Name).IsMaxLength() for example

                                        var setMethod = modelBuilder.GetType()

                                            .GetMethod("Entity", BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy);

                                        // one we have Entity method, we have to add generic parameters
                                        // to get to Entity<T>

                                        var genericSetMethod = setMethod
.MakeGenericMethod(
new Type
[] { set.ItemType });

                                        // Get an instance of EntityTypeConfiguration<T>

                                        var entityInstance = genericSetMethod
Invoke(modelBuilder,
null
);

 

                                        //Get methods of EntityTypeConfiguration<T>

                                        var propertyAccessors = entityInstance.GetType().GetMethods(

                                            BindingFlags.Public | BindingFlags.Instance 
|
BindingFlags
.FlattenHierarchy).ToList();

 

                                        // we are looking for Property method that returns 
                                        // PropertyConfiguration

                                        // that is used in current convention

                                        var propertyMethod =

                                            propertyAccessors.Where(oneProperty =>

                                                oneProperty.ReturnType == 
.PropertyConfigurationType).FirstOrDefault();

 

                                        //Get method handle in order to build the expression

                                        // example: (a => a.Name)

                                        var expressionGetMethod = 
GetPropertyExpressionMethodHandle();

 

                                        //Create lamda expression by making expression method that takes two generic parameters

                                        // one for class, the other for property type

                                        var genericExpressionMethod = expressionGetMethod

                                            .MakeGenericMethod(new Type[] { prop.PropertyInfo.DeclaringType, prop.PropertyInfo.PropertyType });

 

                                        //FInally, get lamda expression it self

                                        // example: (a => a.Name)

                                        var propertyExpression = 
genericExpressionMethod.Invoke(
null, new object
[] { prop.PropertyInfo });

 

                                        //Not get an instance of PrimitivePropertyConfiguration by 
                                        //infoking EntityTypeConfiguration<T>’s

                                        // Property() method

                                        var config = propertyMethod

                                            .Invoke(entityInstance, 
new object[] { propertyExpression }) as PrimitivePropertyConfiguration;

 

                                        //Finally, pass this configuration and attribute into the 
                                        // convention

                                        convention.ApplyConfiguration(prop.PropertyInfo, config, data.Attribute);

                                    }

 

                                });

                        });

                });

            }

        }

 

        /// <summary>

        /// Locate member info handle for GetPropertyExpression method by iterating through

        /// class hierarchy

        /// </summary>

        /// <returns>MemberInfo handle for GetPropertyExpression method</returns>

        private MethodInfo GetPropertyExpressionMethodHandle()

        {

            MethodInfo returnValue = null;

            Type currentType = this.GetType();

            while (returnValue == null)

            {

                returnValue = currentType

                                .GetMethod("GetPropertyExpression",

                                BindingFlags.NonPublic | BindingFlags.FlattenHierarchy 
|
BindingFlags
.Static);

                if (returnValue == null)

                {

                    currentType = currentType.BaseType;

                    if (currentType == null)

                    {

                        break;

                    }

                }

            }

            return returnValue;

        }

 

        /// <summary>

        /// Create Expression that can access property on a class.  You would typically write it as

        /// (p=>p.Name)

        /// In our case we are using Expression to build the same expression

        /// </summary>

        /// <typeparam name="TClass">Class type that is owning the property in question</typeparam>

        /// <typeparam name="TProperty">Property type</typeparam>

        /// <param name="property">PropertyInfo object for property in question</param>

        /// <returns>Expression that returns the property, such as (p=>p.Name)</returns>

        private static Expression<Func<TClass, TProperty>> GetPropertyExpression<TClass, TProperty>(PropertyInfo property)

        {

            //  Create {p=> portion of the Epxression in example (p=>p.Name)

            var objectExpression = Expression.Parameter(property.DeclaringType, "param");

            // create property expression – .Name for example

            var propertyExpression = Expression.Property(objectExpression, property);

            //Create lambda expression from two parts

            var returnValue = Expression.Lambda<Func<TClass, TProperty>>(propertyExpression, objectExpression);

            return returnValue;

        }

 

        /// <summary>

        /// RUn through DbContnxt sets and save reflection data in a dictionary

        /// </summary>

        private void PopulateSetMetadata()

        {

            if (!dbSetMetadata.ContainsKey(this.GetType().AssemblyQualifiedName))

            {

                lock (locker)

                {

                    if (!dbSetMetadata.ContainsKey(this.GetType().AssemblyQualifiedName))

                    {

                        var props = this.GetType().GetProperties(

                            BindingFlags.Public | BindingFlags.Instance | 
BindingFlags
.FlattenHierarchy).ToList();

                        List<DbSetMetadata> sets = new List<DbSetMetadata>();

                        props.ForEach(one =>

                        {

                            //Filter out db sets

                            if (one.PropertyType.IsGenericType &&

                                (one.PropertyType.GetGenericTypeDefinition() == typeof(DbSet<>) ||

                                one.PropertyType.GetGenericTypeDefinition() == typeof(IDbSet<>)))

                            {

                                sets.Add(new DbSetMetadata(one.PropertyType.GetGenericArguments().First(), one));

                            }

                        });

                        // add this context to diutionary

                        dbSetMetadata.Add(this.GetType().AssemblyQualifiedName, sets);

                    }

                }

            }

        }

    }

}

 

That is all.  Feel free to use the code.  Please contact me (use Contact page) if you would like me to create CodePlex project for this sample of extend it further.

Here is what my inherited sample DbContext looks like:

        public class CustomContext: ExtendedDbContext

        {

            public IDbSet<Person> Perosns { get; set; }

 

            protected override void AddConventions()

            {

                AddConvention(new EtendedStringConvention());

            }

 

        }

 

 

You can download full project here.

Thanks.

Post to Twitter

Entity Framework Code First Caching

As I was playing around with Entity Framework code first and ASP.NET MVC, it became pretty obvious that caching of some of the EF query results would be pretty handy.  For example, if you look at my post that includes a simple ASP.NET MVC blogging application, you could see that I have to keep fetching the list of categories every time I render the blog entry screen.  This is because I want to keep my application stateless.  This is not very efficient.

As a result, I looked around for some caching options.  There is a second-level cache project that was published on Microsoft code.  Here is the link to it.  This is very involved and handy project, but currently does not support EF 4.1 (official release name for a number of features, including Code First).  You can download release candidate here or get it from NuGet inside Visual Studio 2010.

Also, I wanted something more explicit, such as extension method to specify that I want to cache results of a specific query.  Here is how I wrote a simple extension method:

        public static IEnumerable<T> AsCacheable<T>(this IQueryable<T> query)

        {

            if (cacheProvider == null)

            {

                throw new InvalidOperationException("Please set cache provider (call SetCacheProvider) before using caching");

            }

            return cacheProvider.GetOrCreateCache<T>(query);

        }

 

I envision my final usage of new functionality will look a following:

 

EFCacheExtensions.SetCacheProvider(MemoryCacheProvider.GetInstance());

using (ProductContext context = new ProductContext())

{

  var query = context.Products.OrderBy(one => one.ProductNumber).
    Where(one => one.IsActive).AsCacheable();

 

}

 

In the example above, I am using in-memory cache provider I wrote.  This provider is using static memory variable to cache data.  This is poor man’s caching solution every day.  To elaborate, this approach works in any environment.  If you are using think client, such as WPF or Windows forms, the cache will stay in memory as long as the application is running.  This is because of the rule of garbage collector.  Static variables are never garbage collected.  In case of web application, such as WCF, the static variables will leave as long as application pool lives.  They will be lost when application pool is recycled.  Default time for app pool recycling in IIS 7 is 20 minutes.  This means that your cache will not live very long.  So, I am also going to implement a provider that is using AppFabric Caching (formerly known as project Velocity).

Since I would like to have an abstraction over both, so that I do not have to change the code going from Velocity to In-Memory provider, I will create an interface to deal with that.

    public interface IEFCacheProvider

    {

        IEnumerable<T> GetOrCreateCache<T>(IQueryable<T> query);

        IEnumerable<T> GetOrCreateCache<T>(IQueryable<T> query, TimeSpan cacheDuration);

        bool RemoveFromCache<T>(IQueryable<T> query);

    }

 

Now, the key code is to implement both providers.  I am going to explain memory provider first.  Here is the class

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Collections.Concurrent;

 

namespace EFCodeFirstCacheExtensions

{

    public class MemoryCacheProvider : IEFCacheProvider

    {

        private MemoryCacheProvider() { }

 

        public static MemoryCacheProvider GetInstance()

        {

            lock (locker)

            {

                if (dictionary == null)

                {

                    dictionary = new ConcurrentDictionary<string, CacheItem>();

                }

 

                if (instance == null)

                {

                    instance = new MemoryCacheProvider();

                }

            }

            return instance;

        }

 

        private static ConcurrentDictionary<string, CacheItem> dictionary;

        private static MemoryCacheProvider instance;

        private static object locker = new object();

 

        public IEnumerable<T> GetOrCreateCache<T>(IQueryable<T> query, TimeSpan cacheDuration)

        {

            string key = GetKey<T>(query);

 

            CacheItem item = dictionary.GetOrAdd(

                key,

                (keyToFind) => { return new CacheItem()

                    { Item = query.ToList(), AdditionTime = DateTime.Now }; });

 

            if (DateTime.Now.Subtract(item.AdditionTime) > cacheDuration)

            {

                item = dictionary.AddOrUpdate(

                    key,

                    new CacheItem() { Item = item.Item, AdditionTime = DateTime.Now },

                    (keyToFind, oldItem) => { return new CacheItem()

                        { Item = query.ToList(), AdditionTime = DateTime.Now }; });

            }

            foreach (var oneItem in ((List<T>)item.Item))

            {

                yield return oneItem;

            }

        }

 

        public IEnumerable<T> GetOrCreateCache<T>(IQueryable<T> query)

        {

            string key = GetKey<T>(query);

 

            CacheItem item = dictionary.GetOrAdd(

                key,

                (keyToFind) => { return new CacheItem()

                    { Item = query.ToList(), AdditionTime = DateTime.Now }; });

 

            foreach (var oneItem in ((List<T>)item.Item))

            {

                yield return oneItem;

            }

        }

 

        public bool RemoveFromCache<T>(IQueryable<T> query)

        {

            string key = GetKey<T>(query);

            CacheItem item = null;

            return dictionary.TryRemove(key, out item);

        }

 

        private static string GetKey<T>(IQueryable<T> query)

        {

            string key = string.Concat(query.ToString(), "\n\r",

                typeof(T).AssemblyQualifiedName);

            return key;

        }

    }

}

 

 

As you can see, I am implementing the original provider interface.  I am supporting self-expiring as well as non-expiring cache.  I am using a neat feature of EF Code Frist.  If I issue to .ToString() of IQueryable, I will get the actual T-SQL query that will be executed.  I am using it as a key for caching in conjunction with class name (T is the type that is returned by they query).  I have to issue ToList prior to caching because of deferred execution in Entity Framework – query is not executed on the back end until I access at least one result.  So, am caching the results of the query as List<T>, but returning IEnumerable<T> to be more generic.

Next, comes AppFabric provider.  The only difference is that I am using AppFabric caching features.  To write and to test, I have to install AppFabric locally and add references to client DLLs to my project.  Those DLLs are:

Microsoft.ApplicationServer.Caching.Client

Microsoft.ApplicationServer.Caching.Core

Once those are done, I just need to replace any chunks of code that refer to memory to refer to cache object from AppFabric.  Here is the full class:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using EFCodeFirstCacheExtensions;

using Microsoft.ApplicationServer.Caching;

 

namespace AppFabricCacheProvider

{

    public class AppFabricCacheProvider : IEFCacheProvider

    {

        private AppFabricCacheProvider() { }

 

        private static object locker = new object();

        private static AppFabricCacheProvider instance;

        private static DataCache cache;

 

        public static AppFabricCacheProvider GetInstance()

        {

            lock (locker)

            {

                if (instance == null)

                {

                    instance = new AppFabricCacheProvider();

                    DataCacheFactory factory = new DataCacheFactory();

                    cache = factory.GetCache("Default");

                }

            }

            return instance;

        }

        public IEnumerable<T> GetOrCreateCache<T>(IQueryable<T> query, TimeSpan cacheDuration)

        {

            string key = GetKey<T>(query);

 

            var cacheItem = cache.Get(key);

            if (cacheItem == null)

            {

                cache.Put(key, query.ToList(), cacheDuration);

                foreach (var oneItem in query)

                {

                    yield return oneItem;

                }

            }

            else

            {

                foreach (var oneItem in ((List<T>)cacheItem))

                {

                    yield return oneItem;

                }

            }

        }

 

        public IEnumerable<T> GetOrCreateCache<T>(IQueryable<T> query)

        {

            string key = GetKey<T>(query);

 

            var cacheItem = cache.Get(key);

            if (cacheItem == null)

            {

                cache.Put(key, query.ToList());

                foreach (var oneItem in query)

                {

                    yield return oneItem;

                }

            }

            else

            {

                foreach (var oneItem in ((List<T>)cacheItem))

                {

                    yield return oneItem;

                }

            }

        }

 

        public bool RemoveFromCache<T>(IQueryable<T> query)

        {

            string key = GetKey<T>(query);

            CacheItem item = null;

            return cache.Remove(key);

        }

 

        private static string GetKey<T>(IQueryable<T> query)

        {

            string key = string.Concat(query.ToString(), "\n\r",

                typeof(T).AssemblyQualifiedName);

            return key;

        }

    }

}

 

II am using built-in expiration as well instead of computing the expiration myself.  I am using DataCacheFactory to create an instance of cache named Default.  Here is my app.config from my unit test project that supports this code:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

    <!–configSections must be the FIRST element –>

    <configSections>

        <section name="dataCacheClient"

           type="Microsoft.ApplicationServer.Caching.DataCacheClientSection, 
Microsoft.ApplicationServer.Caching.Core, Version=1.0.0.0, 
Culture=neutral, PublicKeyToken=31bf3856ad364e35
"

           allowLocation="true"

           allowDefinition="Everywhere"/>

    </configSections>

 

    <dataCacheClient>

        <hosts>

            <host

               name="SERGEYB-PC1"

               cachePort="22233"/>

        </hosts>

        <localCache

             isEnabled="true"

             sync="TimeoutBased"

             objectCount="100000"

             ttlValue="300" />

 

    </dataCacheClient>

 

    <connectionStrings>

        <add name="ProductConnection"

             connectionString="Server=(local);Database=Products;Trusted_Connection=True;"

             providerName="System.Data.SqlClient"/>

    </connectionStrings>

 

</configuration>

 

Also, I used AppFabric console to create cache named Default.

Here is my unit test code that test usage of my new classes:

        [TestMethod]

        public void MemoryCacheProviderGetOrCreateCacheUsageTest()

        {

            EFCacheExtensions.SetCacheProvider(MemoryCacheProvider.GetInstance());

            using (ProductContext context = new ProductContext())

            {

                var query = context.Products

                    .OrderBy(one => one.ProductNumber)

                    .Where(one => one.IsActive).AsCacheable();

 

                Assert.AreEqual(2, query.Count(), "Should have 2 rows");

 

                SQLCommandHelper.ExecuteNonQuery("Update Products Set IsActive = 0");

 

                query = context.Products

                    .OrderBy(one => one.ProductNumber)

                    .Where(one => one.IsActive).AsCacheable();

                Assert.AreEqual(2, query.Count(), "Should have 2 rows");

 

 

                IQueryable<Product> cleanupQuery = context.Products

                    .OrderBy(one => one.ProductNumber)

                    .Where(one => one.IsActive);

 

                EFCacheExtensions.RemoveFromCache<Product>(cleanupQuery);

 

                query = context.Products

                    .OrderBy(one => one.ProductNumber)

                    .Where(one => one.IsActive).AsCacheable();

                Assert.AreEqual(0, query.Count(), "Should have 0 rows");

 

                EFCacheExtensions.RemoveFromCache<Product>(cleanupQuery);

            }

 

        }

 

This demonstrates my intended use of caching in c – simply add AsCacheable to explicitly cache results of a query.  You can also supply timespan for which the cache will live.

You can download entire solution with unit tests and In-Memory and AppFabric implementations here.

Thanks.

Post to Twitter

Repository Pattern with Entity Framework

Repository pattern is a popular architecture pattern that is used to create data access code / layer for an application.  Basic principal behind the pattern is that business object in your application never talks to database directly, but instead talks to repository that takes POCO classes and also returns POCO classes as results of a query.  This way your business layer does not take on a dependency on a specific database or data access layer implementation.  As we see from experience, data access technology does not see to be handing around for very long.

As I was working on entity framework code first, I decided to take a few minutes to develop a number of  convenience classes that would make it easier to repositories that internally use entity framework code first.  Typically, you would create a repository for a set of classes, and this repository will be responsible for querying some data as well as CUD operations.  For example, if you had a product table, you might have repository with methods such as CreateProduct(Product product), UpdateProduct(Product product), DeleteProduct(Product product), GetProductsOrderedByName(int pageNumber, int rowsPerPage), GetProductsOrderedByNumber(int pageNumber, int rowsPerPage), etc…  As you develop more of your application, you might end up with a whole number of repositories.  A lot of them might have similar or the same methods.

I would like to simplify this approach by creating a generic repository that works with DbContext.  So, I am going to create a generic repository for  context type.

  /// <summary>

    /// Repository base class used with DbContext

    /// </summary>

    /// <typeparam name="TContext">Type of DdContext that this repositiory operates on</typeparam>

    public class EFRepository<TContext> : IDisposable

        where TContext : DbContext, IObjectContextAdapter, new()

    {

        private TContext context;

 

        private EFRepository()

        {

 

        }

        /// <summary>

        /// Create new instance of repository

        /// </summary>

        /// <param name="connecstionStringName">Connection string name from .config file</param>

        public EFRepository(string connecstionStringName)

        {

            context = new TContext();

            context.Database.Connection.ConnectionString =

                ConfigurationManager.ConnectionStrings[connecstionStringName].ConnectionString;

        }

 

        /// <summary>

        /// Dipose repository

        /// </summary>

        public void Dispose()

        {

            if (context != null)

            {

                context.Dispose();

                context = null;

            }

        }

 

As you can see, I am using DbContext as a parameter.  I also force to user to supply connection string.  In constructor I am creating new instance of the context.  As a good little developer, I am using IDisposable interface to dispose of the context.  So far pretty simple.  Next, I would like to write generic query mechanism via Select method.

 

 

        /// <summary>

        /// Select data from database

        /// </summary>

        /// <typeparam name="TItem">Type of data to select</typeparam>

        /// <returns></returns>

        public IQueryable<TItem> Select<TItem>()

           where TItem : class, new()

        {

            PropertyInfo property = GetDbSet(typeof(TItem));

 

            DbSet<TItem> set = property.GetValue(context, null) as DbSet<TItem>;

 

            return set;

        }

 
        private PropertyInfo GetDbSet(Type itemType)
        {
            var properties = typeof(TContext).GetProperties().

Where(item => item.PropertyType.Equals(typeof(DbSet<>).MakeGenericType(itemType)));
 
            return properties.First();
        }

 

My select method returns IQueryable.  This way the user of the repository can supply strongly types where and order by clauses as well as Top() and Skip() methods for paging.  Here is an example:

using (EFRepository<ProductContext> repository = new EFRepository<ProductContext>("ProductConnection"))

            {

 

                var ordered = repository.Select<Product>().Where(one => one.IsActive == true).OrderBy(one => one.ProducNumber).ToList();

 

This way I can avoid a whole slew of Select methods and the only dependency I take on is IQueryable, which is a generic interface.in System.Linq namespace located in System.Core.  This to me is a small price to pay for code reduction in repository. 

Next, insert code.  This is super simple of course. 

        /// <summary>

        /// Insert new item into database

        /// </summary>

        /// <typeparam name="TItem">Type of item to insert</typeparam>

        /// <param name="item">Item to insert</param>

        /// <returns>Inserted item</returns>

        public TItem Insert<TItem>(TItem item)

            where TItem : class, new()

        {

            DbSet<TItem> set = GetDbSet(typeof(TItem)).GetValue(context, null) as DbSet<TItem>;

            set.Add(item);

            context.SaveChanges();

            return item;

        }

 

Again, I am using a bit of reflection to find the property DbSet property in the context.  Once I find the set, I add new item to it, fire Save and return new item.  I am using Identity field, and conveniently enough returned item will have the value populated.

Here is an update method:

        /// <summary>

        /// Update na item

        /// </summary>

        /// <typeparam name="TItem">Type of item to update</typeparam>

        /// <param name="item">Item to update</param>

        /// <returns>Updated item</returns>

        public TItem Update<TItem>(TItem item)

            where TItem : class, new()

        {

            DbSet<TItem> set = GetDbSet(typeof(TItem)).GetValue(context, null) as DbSet<TItem>;

            set.Attach(item);

            context.Entry(item).State = System.Data.EntityState.Modified;

            context.SaveChanges();

            return item;

        }

 

Update code is only slightly more complicated.  I am simply setting the state to modified after I am attaching the item in order to force the update.  Delete statement is about the same:

 

 

 

        /// <summary>

        /// Delete an item

        /// </summary>

        /// <typeparam name="TItem">Type of item to delete</typeparam>

        /// <param name="item">Item to delete</param>

        public void Delete<TItem>(TItem item)

           where TItem : class, new()

        {

            DbSet<TItem> set = GetDbSet(typeof(TItem)).GetValue(context, null) as DbSet<TItem>;

            var entry = context.Entry(item);

            if (entry != null)

            {

                entry.State = System.Data.EntityState.Deleted;

            }

            else

            {

                set.Attach(item);

            }

            context.Entry(item).State = System.Data.EntityState.Deleted;

            context.SaveChanges();

        }

The only difference is that I am testing for entity not being in the context, which is really should not be necessary ordinarily, but I ran into an issue like this in my test project, so I added this code to it.

That is all there is to it.  Here is the full class code:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Data.Entity;

using System.Linq.Expressions;

using System.Reflection;

using System.Configuration;

using System.Data.Entity.Infrastructure;

using System.Data.Objects;

 

namespace RepositoryEFCodeFirst

{

    /// <summary>

    /// Repository base class used with DbContext

    /// </summary>

    /// <typeparam name="TContext">Type of DdContext that this repositiory operates on</typeparam>

    public class EFRepository<TContext> : IDisposable

        where TContext : DbContext, IObjectContextAdapter, new()

    {

        private TContext context;

 

        private EFRepository()

        {

 

        }

        /// <summary>

        /// Create new instance of repository

        /// </summary>

        /// <param name="connecstionStringName">Connection string name from .config file</param>

        public EFRepository(string connecstionStringName)

        {

            context = new TContext();

            context.Database.Connection.ConnectionString =

                ConfigurationManager.ConnectionStrings[connecstionStringName].ConnectionString;

        }

 

        /// <summary>

        /// Dipose repository

        /// </summary>

        public void Dispose()

        {

            if (context != null)

            {

                context.Dispose();

                context = null;

            }

        }

 

 

        /// <summary>

        /// Select data from database

        /// </summary>

        /// <typeparam name="TItem">Type of data to select</typeparam>

        /// <returns></returns>

        public IQueryable<TItem> Select<TItem>()

           where TItem : class, new()

        {

            PropertyInfo property = GetDbSet(typeof(TItem));

 

            DbSet<TItem> set = property.GetValue(context, null) as DbSet<TItem>;

 

            return set;

        }

 

        /// <summary>

        /// Insert new item into database

        /// </summary>

        /// <typeparam name="TItem">Type of item to insert</typeparam>

        /// <param name="item">Item to insert</param>

        /// <returns>Inserted item</returns>

        public TItem Insert<TItem>(TItem item)

            where TItem : class, new()

        {

            DbSet<TItem> set = GetDbSet(typeof(TItem)).GetValue(context, null) as DbSet<TItem>;

            set.Add(item);

            context.SaveChanges();

            return item;

        }

 

        /// <summary>

        /// Update na item

        /// </summary>

        /// <typeparam name="TItem">Type of item to update</typeparam>

        /// <param name="item">Item to update</param>

        /// <returns>Updated item</returns>

        public TItem Update<TItem>(TItem item)

            where TItem : class, new()

        {

            DbSet<TItem> set = GetDbSet(typeof(TItem)).GetValue(context, null) as DbSet<TItem>;

            set.Attach(item);

            context.Entry(item).State = System.Data.EntityState.Modified;

            context.SaveChanges();

            return item;

        }

 

        /// <summary>

        /// Delete an item

        /// </summary>

        /// <typeparam name="TItem">Type of item to delete</typeparam>

        /// <param name="item">Item to delete</param>

        public void Delete<TItem>(TItem item)

           where TItem : class, new()

        {

            DbSet<TItem> set = GetDbSet(typeof(TItem)).GetValue(context, null) as DbSet<TItem>;

            var entry = context.Entry(item);

            if (entry != null)

            {

                entry.State = System.Data.EntityState.Deleted;

            }

            else

            {

                set.Attach(item);

            }

            context.Entry(item).State = System.Data.EntityState.Deleted;

            context.SaveChanges();

        }

 

        private PropertyInfo GetDbSet(Type itemType)

        {

            var properties = typeof(TContext).GetProperties().Where(item => item.PropertyType.Equals(typeof(DbSet<>).MakeGenericType(itemType)));

 

            return properties.First();

        }

 

    }

}

 

Here is sample code that uses this repository:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

namespace RepositoryEFCodeFirst

{

    class Program

    {

        static void Main(string[] args)

        {

            using (EFRepository<ProductContext> repository = new EFRepository<ProductContext>("ProductConnection"))

            {

                Console.WriteLine("Total products in DB : " +

                    repository.Select<Product>().Count().ToString());

 

                Product newProduct = new Product();

                newProduct.ProducName = "Plates";

                newProduct.ProducNumber = "001";

                newProduct.Notes = "SOme notes for plates";

                newProduct.IsActive = true;

 

                newProduct = repository.Insert<Product>(newProduct);

 

                var ordered = repository.Select<Product>().Where(one => one.IsActive == true).OrderBy(one => one.ProducNumber).ToList();

 

                Console.WriteLine("New id is " + newProduct.ProductId.ToString());

 

 

                var aProduct = repository.Select<Product>().Where(one => one.IsActive).First();

                aProduct.ProducName = "Updated Plates";

 

                aProduct = repository.Update<Product>(aProduct);

 

                aProduct = repository.Select<Product>().Where(one => one.ProductId == newProduct.ProductId).First();

                Console.WriteLine("Update name is: " + aProduct.ProducName.ToString());

 

                repository.Delete<Product>(aProduct);

 

            }

        }

    }

}

 

I captured the result of the query (in bold) in profiler of my select with where and order by to ensure the operation takes place on the server.  Here is the query.

SELECT

[Extent1].[ProductId] AS [ProductId],

[Extent1].[ProducNumber] AS [ProducNumber],

[Extent1].[ProducName] AS [ProducName],

[Extent1].[Notes] AS [Notes],

[Extent1].[IsActive] AS [IsActive]

FROM [dbo].[Products] AS [Extent1]

WHERE 1 = [Extent1].[IsActive]

ORDER BY [Extent1].[ProducNumber] ASC

This concludes sample repository pattern implementation for Entity Framework Code First.  On a side note, I have not been blogging quite as much.  As I found out, spending 2-3 hours in the car every day going to/from work is not very conducive to blogging Smile.

Thanks.

Post to Twitter

A Little Programming Humor…

Top 20 Developer Responses to Bug Reports

20. That’s weird.

19. It’s never done that before.

18. It worked yesterday.

17. How is that possible?

16. It must be a hardware problem.

15. What did you type in wrong?

14. There is something funky in your data.

13. I haven’t touched that module in weeks.

12. You must have wrong version.

11. I can’t reproduce that.

10. I can’t test everything.

09. THIS can’t be the source to THAT!

08. It works, but it hasn’t been tested.

07. Somebody must have changed my code.

06. Did you check for a virus on your system?

05. OK, it hangs your system, but do you like it?

04. You can’t use that version on your system.

03. Why do you want to do it that way?

02. What were you doing when the program blew up?

01. I thought I fixed that.

Top 10 Product Team Reactions for Enhancement Requests

10. Gee. We never thought of that.

09. Why do you want that?

08. You bought the product without it, so why should we do the work?

07. Well that was scheduled to go in, but the team was on a golf outing that day.

06. We’re investigating that for future versions.

05. If you had any idea how hard that would be, you wouldn’t ask for it.

04. Some variant of “As if!” or “Yuh, right!”

03. “You can do that now”, followed by either some arcane trick or by something 50 times harder than what they were hoping for.

02. People have been asking for that for 3 versions now and we haven’t done it. Take the hint!

01. We cut that feature out because we couldn’t think up a new buzz work to describe it.

Post to Twitter

The Windows 7 Phone Sweepstakes

Between January 1, 2011 and June 30, 2011, when you develop and submit a Windows Phone 7 app into the Windows Phone Marketplace, you can be eligible for a chance to win a Windows Phone 7 (approximate retail value: $500 U.S.).

Every valid Windows Phone 7 app you submit will earn you one entry into the Sweepstakes drawing, so the more you develop, the more chances you have to win.

Here’s how it works

  1. Register for a Windows Phone Marketplace account
  2. Develop an application designed for the Windows Phone 7 platform
  3. Upload and publish your app to the Windows Phone Marketplace
  4. Fill out the form

You can use code 13VAV on that form.

The Sweepstakes starts at 12:00 a.m. local time, on January 1, 2011, and ends at 11:59 p.m. on June 30, 2011 ("Promotion Period"). The Promotion Period will consist of three (3) separate Entry Periods as follows:

January 1, 2011 – January 31, 2011
February 1, 2011 – March 31, 2011
April 1, 2011 – June 30, 2011

Entries will be eligible for the Entry Period during which they are received only and will not carry over to subsequent Entry Periods. You must enter each Entry Period separately.

For complete contest rules, please visit WindowsPhone7event.com/contestrules.

Post to Twitter

Hosting WCF Data Services on Third Party Hosting Provider

Today I am going to talk about how to create a WCF Data Service and host it using a hosting provider.  My specific example will be using GoDaddy (www.GoDaddy.com).  This is the site where I host my blog.  I already posted on this topic, but was using Azure instead.  If you have a subscription to SQL Azure, you can sign up for WCF Data Service option with a single click (https://www.sqlazurelabs.com/).

The reason I decided to write this post was the fact that I got a question from one of the users of my Windows Phone database CodePlex project.  This developer was trying to speed up a query that was doing full-text search on 30,000 + records on Windows Phone.  My suggestion was to host this data in the cloud instead because then you can use full power of the SQL Server (or other RDBMS) to speed up the data retrieval.

First step is to sign up for the database on GoDaddy.  Most packages they sell offer a database.  My package came up with 1 SQL Server database and 10 MySql databases.  Also, I configured my web site on GoDaddy to use ASP.NET 4.0.  I need to use .NET 4 to get support for Data Services.  I could use either SQL Server of MySql, but will illustrate SQL Server in this post.  Once I created database, I was able to use SSQM (SQL Server Management Studio) to connect to the DB server and add tables to my database. Then, I am going to start on WCF Data Service. 

First of all, I am going to create new empty web application project by going to New Project in VS 2010.

image

Then, I am going to use Entity Framework to create a new model.  To do so I am going to add new item and select ADO.NET Entity Data model.

image

I am going to choose the option to generate from the existing database in the wizard, and I am going to select only the tables I need in the mode.  To connect to SQL Server on GoDaddy I needed to write down server name in the control panel on hosting option on GoDaddy.  I input all the settings into the data model wizard after clicking on New Connection button.

image

Then I am presented with my brand spanking new entity model.

image

Now I need to create WCF Data Service.  To do so, I am going to add new item to my web project and select WCF Data Service this time.  Then I put my simple rule into the service definition, allowing all access only to the tables in my model of course.

namespace CompanyWeb
{
   
public class CompanyWcfDataService : DataService<CompanyEntities
>
    {
       
public static void InitializeService(DataServiceConfiguration
config)
        {
            config.SetEntitySetAccessRule(
"*", EntitySetRights
.All);
            config.SetServiceOperationAccessRule(
"*", ServiceOperationRights
.All);
            config.DataServiceBehavior.MaxProtocolVersion =
DataServiceProtocolVersion.V2;
        }
    }
}

 

So far so good.  Now am I am going to test my setup locally by browsing to /CompanyWcfDataService.svc/ file in my project.  Just right click on it and select Browse.  Then I am going to add ContactRoles to the end of the Url and test that.I am getting the data.  I will get Atom Pub page similar to any RSS feed.  I am just looking for number of records those, since I

Now I need to deploy the web project.  First, use content –> IIS menu to create new folder and mark it as application root as well as enable Anonymous authentication. I am going then to use file manager in GoDaddy control panel to create a folder on my web site and copy all the files for my web project there.  Alternatively you can use FTP.  All I would need is to transfer bin folder, .SVC file and web.config.  Here is the final version of web.config:

<?xml version="1.0" encoding="utf-8"?>
<!–

  For more information on how to configure your ASP.NET application, please visit
  http://go.microsoft.com/fwlink/?LinkId=169433
 
–>
<
configuration
>
    <
system.web
>
        <
customErrors mode="Off"
/>
        <
compilation debug="true"
/>
    </
system.web
>
    <
system.webServer
>
        <
httpErrors errorMode="Detailed"
/>
        <
asp scriptErrorSentToBrowser="true"
/>
    </
system.webServer
>
    <
connectionStrings
>
        <
add name="CompanyEntities" connectionString="metadata=res://*/CompanyModel.csdl|res://*/CompanyModel.ssdl|res://*/CompanyModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=serverIP;Initial Catalog=DBName;Persist Security Info=True;User ID=UserID;Password=Password;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient"
/>
    </
connectionStrings
>
    <
system.serviceModel
>
        <
serviceHostingEnvironment aspNetCompatibilityEnabled="true"
>
            <
baseAddressPrefixFilters
>
                <
clear
/>
                <
add prefix="http://www.yoursite.com/yourservicefolder/"/>
            </
baseAddressPrefixFilters
>
        </
serviceHostingEnvironment
>
        <
behaviors
>
            <
serviceBehaviors
>
                <
behavior
>
                    <
serviceDebug includeExceptionDetailInFaults="true"
/>
                </
behavior
>
            </
serviceBehaviors
>
        </
behaviors
>
    </
system.serviceModel
>
</
configuration
>

 

A couple of things to point out.  I am using configuration under system.web to troubleshoot errors.  I have to update service hosting environment to configure prefix to filter out requests I need.  Behavior is also setup to easy in troubleshooting. 

When all said and done, I am testing the service in IQ using the address of my service http://www.yoursite.com/yourservicefolder/CompanyWcfDataService.svc/ContactRoles

Then I got an error – IIS specified authentication schemes ‘Basic, Anonymous’, but the binding only supports specification of exactly one authentication scheme. Valid authentication schemes are Digest, Negotiate, NTLM, Basic, or Anonymous. Change the IIS settings so that only a single authentication scheme is used. To solve this I had to call GoDaddy support to ask them to turn off basic authentication on my site.  That was the last step.

Now, you can simply add a reference to the new service in your Silverlight or phone application.  See my previous posts for details on the process.

A couple of final thoughts.

  • If you are transferring sensitive data, consider buying SSL certificate.
  • Use error configuration to troubleshoot deployment issues.
  • You can use MySQL database with entity framework, you just need to download appropriate provider.
  • Almost exact same process applies to traditional WCF Service.

Please let me know if you have any questions.

Post to Twitter

CodeStock – Voting for Sessions is Now Open

The CodeStock website is now open for registrations and the voting on sessions has begun.  Selections will be announced after March 21st, 2011.

I submitted a number of sessions.  If you would like to see me speak at CodeStock, vote for my sessions please.

Here is my full list:

  • Using Code First (Code Only) approach with Entity Framework
  • Testing SL applications with Microsoft Unit Testing Framework and Coded UI
  • Using LightSwitch for Visual Studio to Quickly Build Silverlight 3 tier applications
  • Working with SQL Azure
  • Using CSLA 4.0 to Build Powerful Enterprise Applications
  • Building ASP.NET MVC 3.0 Applications with Razor View Engine and EF Code First.
  • Working with Data on Windows Phone 7

 

Thank you.

Post to Twitter

Enterprise Library Database Logging and TransactionScope

I have recently worked on a project that was using enterprise library logging capabilities.  Enterprise Libiary information can be viewed on pattern and practices web site.  These library includes a number of useful components,  The one I am going to cover here is database logging capabilities.

Logging features allows an application to be configured to log information about itself into a destination such as Windows event log, text file or database.  We decided to use database logging because of easy of access, less possibility of contention than text file and ability to easy report off this information.  To install logging  you just have to run a script to create and configure the database.  If you installed Enterprise Library, you will find the script in \Blocks\Logging\Src\DatabaseTraceListener\Scripts folder under the source code location which you will need to install as well.  Then, you can use configuration tool that ships with the library to configure it.  If you have application configuration file already part of your solution, you can right-click on it and choose Edit Enterprise Library Configuration menu.  Once, we completed those steps, we noticed that some errors where not logged.  What was strange is that I saw gaps in identity column values in log table.  This led me to believe that errors were logged, but not committed.  Upon further investigation, I found out that logging transactions where rolled back when application errors occurred.   Main reason for that was that our data access code was wrapped inside TransactionScope block.  This happen to be a feature that logging to database has – it does not opt out of ambient transaction scope.  This can be done by using overloaded constructor:

using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Suppress))
{

 

 

This setup allows the code to opt out of ambient transaction established with TransactionScope.

Next I am going to create a couple of my own classes to replace the ones that come with Enterprise Library database logging: FormattedDatabaseTraceListener and FormattedDatabaseTraceListenerData.  You need to replace both because they work in conjunction.  The only difference in FormattedDatabaseTraceListenerData is the creation of trace listener based on our new type:

 

using System;
using System.Configuration;
using System.Diagnostics;
using System.Linq.Expressions;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ContainerModel;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.Design;
using Microsoft.Practices.EnterpriseLibrary.Data.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Logging.Configuration;
using
Microsoft.Practices.EnterpriseLibrary.Logging.Formatters;
 

namespace
Logging
{
   
/// <summary>
    /// Configuration object for a <see cref="FormattedDatabaseTraceListener"/>.
    /// </summary>
    [AddSateliteProviderCommand("connectionStrings", typeof(DatabaseSettings), "DefaultDatabase", "DatabaseInstanceName"
)]
   
public class FormattedDatabaseTraceListenerData : TraceListenerData
    {
       
private const string addCategoryStoredProcNameProperty = "addCategoryStoredProcName"
;
       
private const string databaseInstanceNameProperty = "databaseInstanceName"
;
       
private const string formatterNameProperty = "formatter"
;
       
private const string writeLogStoredProcNameProperty = "writeLogStoredProcName"
;
 
       
/// <summary>
        /// Initializes a <see cref="FormattedDatabaseTraceListenerData"/>.
        /// </summary>
        public
FormattedDatabaseTraceListenerData()
            :
base(typeof(FormattedDatabaseTraceListener
))
        {
           
this.ListenerDataType = typeof(FormattedDatabaseTraceListenerData
);
        }
 
       
/// <summary>
        /// Initializes a named instance of <see cref="FormattedDatabaseTraceListenerData"/> with
        /// name, stored procedure name, databse instance name, and formatter name.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="writeLogStoredProcName">The stored procedure name for writing the log.</param>
        /// <param name="addCategoryStoredProcName">The stored procedure name for adding a category for this log.</param>
        /// <param name="databaseInstanceName">The database instance name.</param>
        /// <param name="formatterName">The formatter name.</param>       
        public FormattedDatabaseTraceListenerData(string
name,
                                                 
string
writeLogStoredProcName,
                                                 
string
addCategoryStoredProcName,
                                                 
string
databaseInstanceName,
                                                 
string
formatterName)
            :
this
(
                name,
                writeLogStoredProcName,
                addCategoryStoredProcName,
                databaseInstanceName,
                formatterName,
               
TraceOptions
.None,
               
SourceLevels
.All)
        {
        }
 
       
/// <summary>
        /// Initializes a named instance of <see cref="FormattedDatabaseTraceListenerData"/> with
        /// name, stored procedure name, databse instance name, and formatter name.
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="writeLogStoredProcName">The stored procedure name for writing the log.</param>
        /// <param name="addCategoryStoredProcName">The stored procedure name for adding a category for this log.</param>
        /// <param name="databaseInstanceName">The database instance name.</param>
        /// <param name="formatterName">The formatter name.</param>
        /// <param name="traceOutputOptions">The trace options.</param>
        /// <param name="filter">The filter to be applied</param>
        public FormattedDatabaseTraceListenerData(string
name,
                                                 
string
writeLogStoredProcName,
                                                 
string
addCategoryStoredProcName,
                                                 
string
databaseInstanceName,
                                                 
string
formatterName,
                                                 
TraceOptions
traceOutputOptions,
                                                 
SourceLevels
filter)
            :
base(name, typeof(FormattedDatabaseTraceListener
), traceOutputOptions, filter)
        {
            DatabaseInstanceName = databaseInstanceName;
            WriteLogStoredProcName = writeLogStoredProcName;
            AddCategoryStoredProcName = addCategoryStoredProcName;
            Formatter = formatterName;
        }
 
       
/// <summary>
        /// Gets and sets the database instance name.
        /// </summary>
        [ConfigurationProperty(databaseInstanceNameProperty, IsRequired = true
)]
       
public string
DatabaseInstanceName
        {
           
get { return (string)base
[databaseInstanceNameProperty]; }
           
set { base[databaseInstanceNameProperty] = value
; }
        }
 
       
/// <summary>
        /// Gets and sets the stored procedure name for writing the log.
        /// </summary>
        [ConfigurationProperty(writeLogStoredProcNameProperty, IsRequired = true, DefaultValue = "WriteLog"
)]
       
public string
WriteLogStoredProcName
        {
           
get { return (string)base
[writeLogStoredProcNameProperty]; }
           
set { base[writeLogStoredProcNameProperty] = value
; }
        }
 
       
/// <summary>
        /// Gets and sets the stored procedure name for adding a category for this log.
        /// </summary>
        [ConfigurationProperty(addCategoryStoredProcNameProperty, IsRequired = true, DefaultValue = "AddCategory"
)]
       
public string
AddCategoryStoredProcName
        {
           
get { return (string)base
[addCategoryStoredProcNameProperty]; }
           
set { base[addCategoryStoredProcNameProperty] = value
; }
        }
 
       
/// <summary>
        /// Gets and sets the formatter name.
        /// </summary>
        [ConfigurationProperty(formatterNameProperty, IsRequired = false
)]
       
public string
Formatter
        {
           
get { return (string)base
[formatterNameProperty]; }
           
set { base[formatterNameProperty] = value
; }
        }
 
       
/// <summary>
        /// Returns a lambda expression that represents the creation of the trace listener described by this
        /// configuration object.
        /// </summary>
        /// <returns>A lambda expression to create a trace listener.</returns>
        protected override Expression<Func<TraceListener
>> GetCreationExpression()
        {
           
return
() =>
                  
new FormattedDatabaseTraceListener
(
                      
Container.Resolved<Microsoft.Practices.EnterpriseLibrary.Data.Database
>(DatabaseInstanceName),
                       WriteLogStoredProcName,
                       AddCategoryStoredProcName,
                      
Container.ResolvedIfNotNull<ILogFormatter>(Formatter));
        }
    }
}

 

I kept the rest of the code the same.  Listener itself has more changes, specifically, I am wrapping all database access code with new transaction scope:

using System;
using System.Data;
using System.Data.Common;
using System.Diagnostics;
using System.Globalization;
using System.Transactions;
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using Microsoft.Practices.EnterpriseLibrary.Logging.Formatters;
using
Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners;
 

namespace
Logging
{
   
/// <summary>
    /// A <see cref="System.Diagnostics.TraceListener"/> that writes to a database, formatting the output with an <see cref="ILogFormatter"/>.
    /// </summary>
    [ConfigurationElementType(typeof(FormattedDatabaseTraceListenerData
))]
   
public class FormattedDatabaseTraceListener : FormattedTraceListenerBase
    {
       
string writeLogStoredProcName = String
.Empty;
       
string addCategoryStoredProcName = String
.Empty;
        Microsoft.Practices.EnterpriseLibrary.Data.
Database
database;
 
       
/// <summary>
        /// Initializes a new instance of <see cref="FormattedDatabaseTraceListener"/>.
        /// </summary>
        /// <param name="database">The database for writing the log.</param>
        /// <param name="writeLogStoredProcName">The stored procedure name for writing the log.</param>
        /// <param name="addCategoryStoredProcName">The stored procedure name for adding a category for this log.</param>
        /// <param name="formatter">The formatter.</param>       
        public
FormattedDatabaseTraceListener(
            Microsoft.Practices.EnterpriseLibrary.Data.
Database
database,
           
string
writeLogStoredProcName,
           
string
addCategoryStoredProcName,
           
ILogFormatter
formatter)
            :
base
(formatter)
        {
           
this
.writeLogStoredProcName = writeLogStoredProcName;
           
this
.addCategoryStoredProcName = addCategoryStoredProcName;
           
this
.database = database;
        }
 
       
/// <summary>
        /// The Write method
        /// </summary>
        /// <param name="message">The message to log</param>
        public override void Write(string
message)
        {
           
using (TransactionScope scope = new TransactionScope(TransactionScopeOption
.Suppress))
            {
               
using (DbConnection
connection = database.CreateConnection())
                {
                    connection.Open();
                   
try
                    {
                       
using (DbTransaction
transaction = connection.BeginTransaction())
                        {
                           
try
                            {
                                ExecuteWriteLogStoredProcedure(0, 5,
TraceEventType.Information, string.Empty, DateTime.Now, string
.Empty,
                                           
string.Empty, string.Empty, string.Empty, null, null
, message, database);
                                transaction.Commit();
                            }
                           
catch
                            {
                                transaction.Rollback();
                               
throw
;
                            }
                        }
                    }
                   
finally
                    {
                        connection.Close();
                    }
                }
                scope.Complete();
            }
           
        }
 
       
/// <summary>
        /// The WriteLine method.
        /// </summary>
        /// <param name="message">The message to log</param>
        public override void WriteLine(string
message)
        {
            Write(message);
        }
 
 
       
/// <summary>
        /// Delivers the trace data to the underlying database.
        /// </summary>
        /// <param name="eventCache">The context information provided by <see cref="System.Diagnostics"/>.</param>
        /// <param name="source">The name of the trace source that delivered the trace data.</param>
        /// <param name="eventType">The type of event.</param>
        /// <param name="id">The id of the event.</param>
        /// <param name="data">The data to trace.</param>
        public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, object
data)
        {
           
if ((this.Filter == null) || this.Filter.ShouldTrace(eventCache, source, eventType, id, null, null, data, null
))
            {
               
if (data is LogEntry
)
                {
                   
LogEntry logEntry = data as LogEntry
;
                   
if
(ValidateParameters(logEntry))
                        ExecuteStoredProcedure(logEntry);
                }
               
else if (data is string
)
                {
                    Write(data
as string
);
                }
               
else
                {
                   
base
.TraceData(eventCache, source, eventType, id, data);
                }
            }
        }
 
       
/// <summary>
        /// Declare the supported attributes for <see cref="FormattedDatabaseTraceListener"/>
        /// </summary>
        protected override string
[] GetSupportedAttributes()
        {
           
return new string[4] { "formatter", "writeLogStoredProcName", "addCategoryStoredProcName", "databaseInstanceName"
};
        }
 
       
/// <summary>
        /// Validates that enough information exists to attempt executing the stored procedures
        /// </summary>
        /// <param name="logEntry">The LogEntry to validate.</param>
        /// <returns>A Boolean indicating whether the parameters for the LogEntry configuration are valid.</returns>
        private bool ValidateParameters(LogEntry
logEntry)
        {
           
bool valid = true
;
 
           
if (writeLogStoredProcName == null
||
                writeLogStoredProcName.Length == 0)
            {
               
return false
;
            }
 
           
if (addCategoryStoredProcName == null
||
                addCategoryStoredProcName.Length == 0)
            {
               
return false
;
            }
 
           
return
valid;
        }
 
       
/// <summary>
        /// Executes the stored procedures
        /// </summary>
        /// <param name="logEntry">The LogEntry to store in the database</param>
        private void ExecuteStoredProcedure(LogEntry
logEntry)
        {
           
using (TransactionScope scope = new TransactionScope(TransactionScopeOption
.Suppress))
            {
               
using (DbConnection
connection = database.CreateConnection())
                {
                    connection.Open();
                   
try
                    {
                       
using (DbTransaction
transaction = connection.BeginTransaction())
                        {
                           
try
                            {
                               
int logID = Convert
.ToInt32(ExecuteWriteLogStoredProcedure(logEntry, database, transaction));
                                ExecuteAddCategoryStoredProcedure(logEntry, logID, database, transaction);
                                transaction.Commit();
                            }
                           
catch
                            {
                                transaction.Rollback();
                               
throw
;
                            }
 
                        }
                    }
                   
finally
                    {
                        connection.Close();
                    }
                }
                scope.Complete();
            }
        }
 
       
/// <summary>
        /// Executes the WriteLog stored procedure
        /// </summary>
        /// <param name="eventId">The event id for this LogEntry.</param>
        /// <param name="priority">The priority for this LogEntry.</param>
        /// <param name="severity">The severity for this LogEntry.</param>
        /// <param name="title">The title for this LogEntry.</param>
        /// <param name="timeStamp">The timestamp for this LogEntry.</param>
        /// <param name="machineName">The machine name for this LogEntry.</param>
        /// <param name="appDomainName">The appDomainName for this LogEntry.</param>
        /// <param name="processId">The process id for this LogEntry.</param>
        /// <param name="processName">The processName for this LogEntry.</param>
        /// <param name="managedThreadName">The managedthreadName for this LogEntry.</param>
        /// <param name="win32ThreadId">The win32threadID for this LogEntry.</param>
        /// <param name="message">The message for this LogEntry.</param>
        /// <param name="db">An instance of the database class to use for storing the LogEntry</param>
        /// <returns>An integer for the LogEntry Id</returns>
        private int ExecuteWriteLogStoredProcedure(int eventId, int priority, TraceEventType severity, string title, DateTime
timeStamp,
                                                   
string machineName, string appDomainName, string processId, string
processName,
                                                   
string managedThreadName, string win32ThreadId, string message, Microsoft.Practices.EnterpriseLibrary.Data.Database
db)
        {
           
using (TransactionScope scope = new TransactionScope(TransactionScopeOption
.Suppress))
            {
               
DbCommand
cmd = db.GetStoredProcCommand(writeLogStoredProcName);
 
                db.AddInParameter(cmd,
"eventID", DbType
.Int32, eventId);
                db.AddInParameter(cmd,
"priority", DbType
.Int32, priority);
                db.AddParameter(cmd,
"severity", DbType.String, 32, ParameterDirection.Input, false, 0, 0, null, DataRowVersion
.Default, severity.ToString());
                db.AddParameter(cmd,
"title", DbType.String, 256, ParameterDirection.Input, false, 0, 0, null, DataRowVersion
.Default, title);
                db.AddInParameter(cmd,
"timestamp", DbType
.DateTime, timeStamp);
                db.AddParameter(cmd,
"machineName", DbType.String, 32, ParameterDirection.Input, false, 0, 0, null, DataRowVersion
.Default, machineName);
                db.AddParameter(cmd,
"AppDomainName", DbType.String, 512, ParameterDirection.Input, false, 0, 0, null, DataRowVersion
.Default, appDomainName);
                db.AddParameter(cmd,
"ProcessID", DbType.String, 256, ParameterDirection.Input, false, 0, 0, null, DataRowVersion
.Default, processId);
                db.AddParameter(cmd,
"ProcessName", DbType.String, 512, ParameterDirection.Input, false, 0, 0, null, DataRowVersion
.Default, processName);
                db.AddParameter(cmd,
"ThreadName", DbType.String, 512, ParameterDirection.Input, false, 0, 0, null, DataRowVersion
.Default, managedThreadName);
                db.AddParameter(cmd,
"Win32ThreadId", DbType.String, 128, ParameterDirection.Input, false, 0, 0, null, DataRowVersion
.Default, win32ThreadId);
                db.AddParameter(cmd,
"message", DbType.String, 1500, ParameterDirection.Input, false, 0, 0, null, DataRowVersion
.Default, message);
                db.AddInParameter(cmd,
"formattedmessage", DbType
.String, message);
 
                db.AddOutParameter(cmd,
"LogId", DbType
.Int32, 4);
 
                db.ExecuteNonQuery(cmd);
               
int logId = Convert.ToInt32(cmd.Parameters[cmd.Parameters.Count - 1].Value, CultureInfo
.InvariantCulture);
                scope.Complete();
               
return
logId;
            }
        }
 
       
/// <summary>
        /// Executes the WriteLog stored procedure
        /// </summary>
        /// <param name="logEntry">The LogEntry to store in the database.</param>
        /// <param name="db">An instance of the database class to use for storing the LogEntry</param>
        /// <param name="transaction">The transaction that wraps around the execution calls for storing the LogEntry</param>
        /// <returns>An integer for the LogEntry Id</returns>
        private int ExecuteWriteLogStoredProcedure(LogEntry logEntry, Microsoft.Practices.EnterpriseLibrary.Data.Database db, DbTransaction
transaction)
        {
           
using (TransactionScope scope = new TransactionScope(TransactionScopeOption
.Suppress))
            {
               
DbCommand
cmd = db.GetStoredProcCommand(writeLogStoredProcName);
 
 
                db.AddInParameter(cmd,
"eventID", DbType
.Int32, logEntry.EventId);
                db.AddInParameter(cmd,
"priority", DbType
.Int32, logEntry.Priority);
                db.AddParameter(cmd,
"severity", DbType.String, 32, ParameterDirection.Input, false, 0, 0, null, DataRowVersion
.Default, logEntry.Severity.ToString());
                db.AddParameter(cmd,
"title", DbType.String, 256, ParameterDirection.Input, false, 0, 0, null, DataRowVersion
.Default, logEntry.Title);
                db.AddInParameter(cmd,
"timestamp", DbType
.DateTime, logEntry.TimeStamp);
                db.AddParameter(cmd,
"machineName", DbType.String, 32, ParameterDirection.Input, false, 0, 0, null, DataRowVersion
.Default, logEntry.MachineName);
                db.AddParameter(cmd,
"AppDomainName", DbType.String, 512, ParameterDirection.Input, false, 0, 0, null, DataRowVersion
.Default, logEntry.AppDomainName);
                db.AddParameter(cmd,
"ProcessID", DbType.String, 256, ParameterDirection.Input, false, 0, 0, null, DataRowVersion
.Default, logEntry.ProcessId);
                db.AddParameter(cmd,
"ProcessName", DbType.String, 512, ParameterDirection.Input, false, 0, 0, null, DataRowVersion
.Default, logEntry.ProcessName);
                db.AddParameter(cmd,
"ThreadName", DbType.String, 512, ParameterDirection.Input, false, 0, 0, null, DataRowVersion
.Default, logEntry.ManagedThreadName);
                db.AddParameter(cmd,
"Win32ThreadId", DbType.String, 128, ParameterDirection.Input, false, 0, 0, null, DataRowVersion
.Default, logEntry.Win32ThreadId);
                db.AddParameter(cmd,
"message", DbType.String, 1500, ParameterDirection.Input, false, 0, 0, null, DataRowVersion
.Default, logEntry.Message);
 
               
if (Formatter != null
)
                    db.AddInParameter(cmd,
"formattedmessage", DbType
.String, Formatter.Format(logEntry));
               
else
                    db.AddInParameter(cmd, "formattedmessage", DbType
.String, logEntry.Message);
 
                db.AddOutParameter(cmd,
"LogId", DbType
.Int32, 4);
 
                db.ExecuteNonQuery(cmd, transaction);
               
int logId = Convert.ToInt32(cmd.Parameters[cmd.Parameters.Count - 1].Value, CultureInfo
.InvariantCulture);
                scope.Complete();
               
return
logId;
               
            }
        }
 
       
/// <summary>
        /// Executes the AddCategory stored procedure
        /// </summary>
        /// <param name="logEntry">The LogEntry to store in the database.</param>
        /// <param name="logID">The unique identifer for the LogEntry as obtained from the WriteLog Stored procedure.</param>
        /// <param name="db">An instance of the database class to use for storing the LogEntry</param>
        /// <param name="transaction">The transaction that wraps around the execution calls for storing the LogEntry</param>
        private void ExecuteAddCategoryStoredProcedure(LogEntry logEntry, int logID, Microsoft.Practices.EnterpriseLibrary.Data.Database db, DbTransaction
transaction)
        {
           
using (TransactionScope scope = new TransactionScope(TransactionScopeOption
.Suppress))
            {
               
foreach (string category in
logEntry.Categories)
                {
                   
DbCommand
cmd = db.GetStoredProcCommand(addCategoryStoredProcName);
                    db.AddInParameter(cmd,
"categoryName", DbType
.String, category);
                    db.AddInParameter(cmd,
"logID", DbType.Int32, logID);
                    db.ExecuteNonQuery(cmd, transaction);
                }
                scope.Complete();
            }
        }
    }
}

 

The last step is to replace preloaded listener types with our own as in below:

<?xml version="1.0" encoding="utf-8" ?>
<
configuration
>
    <
configSections
>
        <
section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true"
/>
        <
section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true"
/>
    </
configSections
>
    <
loggingConfiguration name="" tracingEnabled="true" defaultCategory="General"
>
        <
listeners
>
            <
add name="Database Trace Listener"
                type="Logging.FormattedDatabaseTraceListener, Logging, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
                istenerDataType="Logging.FormattedDatabaseTraceListenerData, Logging, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
                databaseInstanceName="Logging"
                writeLogStoredProcName="WriteLog"
                addCategoryStoredProcName="AddCategory"
/>
        </
listeners
>
        <
formatters
>
            <
add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
                template="Timestamp: {timestamp}{newline}&#xA;Message: {message}{newline}&#xA;Category: {category}{newline}&#xA;Priority: {priority}{newline}&#xA;EventId: {eventid}{newline}&#xA;Severity: {severity}{newline}&#xA;Title:{title}{newline}&#xA;Machine: {localMachine}{newline}&#xA;App Domain: {localAppDomain}{newline}&#xA;ProcessId: {localProcessId}{newline}&#xA;Process Name: {localProcessName}{newline}&#xA;Thread Name: {threadName}{newline}&#xA;Win32 ThreadId:{win32ThreadId}{newline}&#xA;Extended Properties: {dictionary({key} – {value}{newline})}"
                name="Text Formatter"
/>
        </
formatters
>
        <
categorySources
>
            <
add switchValue="All" name="General"
>
                <
listeners
>
                    <
add name="Database Trace Listener"
/>
                </
listeners
>
            </
add
>
        </
categorySources
>
        <
specialSources
>
            <
allEvents switchValue="All" name="All Events"
/>
            <
notProcessed switchValue="All" name="Unprocessed Category"
/>
            <
errors switchValue="All" name="Logging Errors &amp; Warnings"
>
                <
listeners
>
                    <
add name="Database Trace Listener"
/>
                </
listeners
>
            </
errors
>
        </
specialSources
>
    </
loggingConfiguration
>
    <
dataConfiguration defaultDatabase="Logging"
/>
    <
connectionStrings
>
        <
add name="Logging" connectionString="Logging" providerName="System.Data.SqlClient"
/>
    </
connectionStrings
>
</
configuration
>

 

That is all there is to using Enterprise Library database logging within existing transaction scope.  You can download the project here.  You will need to download and install Enterprise Library to build it.

Post to Twitter

Working with Data on Windows Phone 7 – Part 2

In this part I am going to use WCF Data Services (formerly known as project Astoria and ADO.NET Data Services) to accomplish the same couple of tasks I did in WCF custom service.  I am going to get a list of people and add a person.

I will use exact same project as I did the last time.  As you recall, I created a database with one table using EF Code First.  This is where I am going to start.  In first step I am going to create an Entity Framework model from that database.  To do so, I am going to add new item to my web project and select Entity Framework model.

image

I will then walk through EF model wizard to generate the model from my database:

image

image

 

image

This will generate my model with my person class.

WCF Data Service will expose my model via web RESTful interfaces.  To add the service, I am going to add new item again, but now select WCF Data Service as item type:

 

image

Next step is to configure WCF Data Service to use my entity model.  This step is pretty easy, since service is a generic type with a parameter that takes entity model

    public class PersonWcfDataService : DataService<PersonsDbEntities>
    {
       
public static void InitializeService(DataServiceConfiguration
config)
        {
            config.SetEntitySetAccessRule(
"*", EntitySetRights
.All);
            config.DataServiceBehavior.MaxProtocolVersion =
DataServiceProtocolVersion.V2;
        }
    }

 

In the code above I am setting rights to all entities to everyone.  In production I would not do this, but it works as illustration.  In my next step I am going to test the service.  I am going to right click on PersonWcfDataService.svc file that was generated in the step above and select View In Browser.

image

Next, I want to make sure I can get the list of people.  I am going to change my Url and test that.  You can see the address and result below:

image

Of course the results look like Atom feed since OData that WCF Data Service implement extends AtomPub protocol.  I can look at the data by selecting view source.  The data looks as following:

image

Next I need to generate proxy for my Phone application.  Unfortunately, add service reference does not work for phone Silverlight applications.  So, I am going to download necessary files from CodePlex to proceed.

Visit http://odata.codeplex.com and download ODataClient_BinariesAndCodeGenToolForWinPhone.zip.  Once it is on your local machine, unblock the zip file in windows properties, otherwise you will get compilation errors later.  Unzip it into a blank folder to make it easy to find later.

Here is the content of the folder:

image

Add a reference to System.Data.Services.Client.dll to your windows phone project.  Now, we need to generate proxy and related classes.  To do so we will use DataSvcUtil.exe from the same folder.  Here is the command line I am using:

 

datasvcutil /uri:http://localhost:50406/PersonWcfDataService.svc/ /out:.\PersonModel.cs /DataServiceCollection /Version:2.0

As you can see I am providing my svc file’s url.  I am using version 2 of the data services.  I am outputting the proxy into PersonModel.cs file.  DataServiceCollection parameter instructs the utility to generate collections that derive from DataSericeCollection.  Next I am include this file in my project.

Next I am going to create an instance of the client in my view model as following:

PersonsDbEntities odataClient;

odataClient =

         new PersonsDbEntities(new Uri(@"http://localhost:50406/PersonWcfDataService.svc"));

 

Of course in production you need to give correct Url.  Next, I am going to query the data.  First I am going to define a property to hold my collection


        private DataServiceCollection<PersonsDbModel.Person> oDataPeople;
 
       
public DataServiceCollection<PersonsDbModel.Person
> ODataPeople
        {
           
get { return
oDataPeople; }
           
set
            {
                oDataPeople =
value
;
                NotifyPropertyChanged(
"ODataPeople");
            }
        }

 

Then I am going to query the data as following

            ODataPeople = new DataServiceCollection<PersonsDbModel.Person>(odataClient);
            ODataPeople.LoadCompleted += ODataPeople_LoadCompleted;
 
           
try
            {
                ODataPeople.LoadAsync(peopleUri);
            }
           
catch (DataServiceClientException
ex)
            {
               
MessageBox.Show(ex.ToString());
            }

 

So, first I create a collection and tie it to my client.  Without that I can query the collection.  In the callback I check for errors:

        void ODataPeople_LoadCompleted(object sender, LoadCompletedEventArgs e)
        {
           
if (e.QueryOperationResponse.Error != null
)
            {
               
MessageBox.Show(e.QueryOperationResponse.Error.ToString());
            }
        }

 

That I it.  Now I just add a listbox to my UI and bind it to this collection:

            <controls:PivotItem Header="oData">
                <!–Double line list with text wrapping–>
                <ListBox x:Name="ODataListBox" Margin="0,0,-12,0"
 
                       
ItemsSource="{Binding ODataPeople}">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                            <StackPanel Margin="0,0,0,17" Width="432">
                                <TextBlock
 
                                
Text="{Binding FirstName}"
 
                                
TextWrapping="Wrap"
 
                                
Style="{StaticResource PhoneTextExtraLargeStyle}"/>
                                <TextBlock
 
                                
Text="{Binding LastName}"
 
                                
TextWrapping="Wrap"
 
                                
Margin="12,-6,12,0"
 
                                
Style="{StaticResource PhoneTextSubtleStyle}"/>
                            </StackPanel>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
            </controls:PivotItem
>

 

Next, adding a person via OData.  It is really simple.  I just add new person to my collection and start the save process.  DataSericeCollection  objects are smart to keep track of the changes that occur during operation on the server.


        public void InsertPersonOdata()
        {
            ODataPeople.Add(
new PersonsDbModel.Person() { FirstName = "James", LastName = "Homer", PersonID = Guid
.NewGuid() });
            odataClient.BeginSaveChanges(
SaveChangesOptions
.Batch, (ar) =>
            {
               
Deployment
.Current.Dispatcher.BeginInvoke(() =>
                {
                    odataClient = ar.AsyncState
as PersonsDbModel.PersonsDbEntities
;
                   
DataServiceResponse
response = odataClient.EndSaveChanges(ar);
                   
if
(response.IsBatchResponse)
                    {
                       
StringBuilder errors = new StringBuilder
();
                       
foreach (ChangeOperationResponse change in
response)
                        {
                           
if (change.Error != null
)
                            {
                                errors.Append(change.Error.ToString());
                            }
                        }
                       
if
(errors.Length == 0)
                        {
                           
MessageBox.Show("Success"
);
                        }
                       
else
                        {
                           
MessageBox.Show(errors.ToString());
                        }
                    }
                });
            }, odataClient);
        }

 

You can download the entire solution for both parts 1 and 2 here.  There does seem to be some flakiness in running both services from one solution, so you may have to comment WCF Service or OData service calls to test each portion.

Post to Twitter

Quick Start Guide for Windows Phone 7 Database

I have a CodePlex project for Isolated Storage based database for Windows phone 7.  You can check out this project at http://winphone7db.codeplex.com/

 

First step is to download the project and build it on your copter.  Visit the download page for the latest recommended download.  Unzip the source code on your machine, open it up in Visual Studio 2010 and compile to create a DLL.

Next, create new Windows Phone 7 project and add a reference to the DLL from step 1.

Next, in your View Model (or elsewhere in your application) check for database existence and create if it does not exist along with tables.  See sample code below

            if (!Database.DoesDatabaseExists(DatabaseName))
            {
                database =
Database
.CreateDatabase(DatabaseName);
                database.CreateTable<
Person
>();
                database.CreateTable<
PersonDetail
>();
                database.Save();
            }
           
else
            {
                database =
Database.OpenDatabase(DatabaseName, string.Empty, true);
            }

In the sample above I am testing if database exists, then create it if it does not,  Then I am adding two tables to it based on POCO classes.  For example, Person class would look like

    public class Person
    {
       
public Guid PersonID { get; set
; }
       
public string FirstName { get; set
; }
       
public string LasstName { get; set; }
    }

 

If you would like to add a row to a table, just issue Add command:

db.Table<Person>().Add(NewPerson());

 

New Person routine just returns Person instance.

To remove, just issue remove command:

 

db.Table<Person>().Remove(person2);

 

You can also remove and add a range of items based on condition.

db.Table<Person>().RemoveRange((person) => { return (person.Salary >= 2); });

 

You can also add a range of items, specifically IEnumerable<T>

db.Table<Person>().AddRange(list);

 

Make sure to call Save() on either database or a specific table to commit your changes.

You can also look in unit test project that is distributed as part of the source code download for other API samples.

Post to Twitter

Working with Data on Windows Phone 7 – Part 1

I am starting a short series of blog posts that will go over various techniques of working with data on Windows Phone 7.  I am going to create a Silverlight application for the phone that gets local and remote data in a number of ways.

I this first post I will build a WCF service and connect to it from phone application.  I am going to use Entity Framework Code Frist approach to expose the data through my WCF Service.

Let’s get started.

Step 1

I am going to create new phone application.  Start Visual Studio 2010 and create new project.  Select a project template for Windows Phone Pivot Application.

image

Now, I forget about pre-generated code and create a WCF service.  To do so, add new project to created solution.  To give you a head start, select template for WCF Service Application.

image

Now, it is time to get Entity Framework code first CTP 5 up and going to create database and access it.  I am going to use NuGet (install it first if you do not have it).  Right click on references in your WCF project and select add Package References.  Choose to search on line and first the CTP 5.

image

I am installing the package which will download the DLL and add references to my project.  I am also adding a reference to System.ComponentModel.DataAnnotations.

Now I am going to add my EF classes, which are POCO classes.  I am going to go for something simple, so I am creating new single object called Person along with my data context.  Person class is very simple and here is the code for it.

using System;
using System.ComponentModel.DataAnnotations;
using
System.Runtime.Serialization;
 

namespace
WcfPhoneService
{
    [
DataContract
]
   
public class Person
    {
        [
Key
]
        [
Required
]
        [
DataMember
]
       
public Guid PersonID { get; set
; }
 
        [
MaxLength
(30)]
        [
Required
]
        [
DataMember
]
       
public string FirstName { get; set
; }
 
        [
MaxLength
(30)]
        [
Required
]
        [
DataMember
]
       
public string LastName { get; set; }
    }
}

 

There are a couple of points worth noticing.  I am using data annotation attributes to denote the requirement of all my future columns in the table.  I am setting the maximum length as well as the key for the table.  I am also setting the WCF required attributes as I am going to be eventually transferring these classes to/from the phone application.  I also need to create the data context, akin to database that will contain my list of persons.  It inherits from base class in EF CTP 5 and contains the list (set) of persons.  Again. code is pretty simple:

using System.Configuration;
using System.Data.Entity;
using
System.Data.Entity.Database;
 

namespace
WcfPhoneService
{
   
public class PersonContext : DbContext
    {
       
public
PersonContext()
        {
           
//Set initializer to handle model changes
            DbDatabase.SetInitializer<PersonContext>(new PersonContextConfig
());
 
           
this
.Database.Connection.ConnectionString =
                   
ConfigurationManager.ConnectionStrings["PersonConnectionString"
]
                    .ConnectionString;
        }
 
       
/// <summary>
        /// List of persons
        /// </summary>
        public IDbSet<Person> Persons { get; set
; }
 
       
/// <summary>
        /// Add custom configurations if necessary
        /// </summary>
        /// <param name="modelBuilder">Model builder</param>
        protected override void OnModelCreating(System.Data.Entity.ModelConfiguration.ModelBuilder
modelBuilder)
        {
           
base.OnModelCreating(modelBuilder);
 
        }
    }
}

 

You can see an extra class in the constructor called PersonContextConfig.  This class simply controls the default database behavior of the context when the model changes.  I am setting it to recreating of the database in my case.  I also added a couple of rows of data just for the demo by overriding Seed method.

using System.Data.Entity.Database;
using
System;
 

namespace
WcfPhoneService
{
   
public class PersonContextConfig : DropCreateDatabaseIfModelChanges<PersonContext
>
    {
       
protected override void Seed(PersonContext
context)
        {
           
base
.Seed(context);
            context.Persons.Add(
new Person() { PersonID = Guid.NewGuid(), FirstName = "John", LastName = "Doe"
});
            context.Persons.Add(
new Person() { PersonID = Guid.NewGuid(), FirstName = "Jane", LastName = "Doe" });
            context.SaveChanges();
        }
    }
}

 

Now, it is time to create my service.  I am going to add just two methods to it – get list of persons and insert a new person.  When project was created, it created default IService1 interface and Service1 implementation.  I am just going to rename both to IPersonService and PersonService respectively.  Then, I am going to implement the two methods above

using System.Collections.Generic;
using
System.ServiceModel;
 

namespace
WcfPhoneService
{
    [
ServiceContract
]
   
public interface IPersonService
    {
        [
OperationContract
]
       
IEnumerable<Person
> GetPeople();
 
        [
OperationContract
]
       
void AddPerson(Person person);
    }
 
 
 
}

 

using System.Collections.Generic;
using
System.Linq;
 

namespace
WcfPhoneService
{
 
   
public class PersonService : IPersonService
    {
       
public IEnumerable<Person
> GetPeople()
        {
           
using (PersonContext context = new PersonContext
())
            {
               
return
context.Persons.OrderBy(one => one.LastName).ThenBy(one => one.FirstName).ToList();
            }
        }
 
       
public void AddPerson(Person
person)
        {
           
using (PersonContext context = new PersonContext())
            {
                context.Persons.Add(person);
                context.SaveChanges();
            }
        }
    }
}

 

Pretty simple, right.  Now I am going to switch to my Phone project.  I am going to remove all pre-generated code from all view models first and build the project to make sure it is all good.  Now, it is time to add a service reference to my WCF project.  To do so, right click on references node in phone project and choose add service reference menu item.  Click on Discover button on the service dialog box.  Change namespace to PersonService for consistency.

image

Click OK and let the studio generate all your code for you.  To see generated code, click on PersonService reference under service references, then click on Show All Files on top of Solution explorer window.  You can then drill down to see Reference.cs.  This contains all your generated code.

image

I am now going to update view model to let it connect to the service and get the list of people.  I have to create an instance of the client (proxy), setup a handler for GetPeople method, then call it.  I also add a property to hold Person collection in.  All fairly simple.  Here is the entire code:

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using
WindowsPhonePivotAppWithData.PersonService;
 
 

namespace
WindowsPhonePivotAppWithData
{
   
public class MainViewModel : INotifyPropertyChanged
    {
        PersonService.
PersonServiceClient client = new PersonService.PersonServiceClient
();
       
public
MainViewModel()
        {
 
        }
 
       
private ObservableCollection<Person
> people;
 
       
public ObservableCollection<Person
> People
        {
           
get { return
people; }
           
private set { people = value; NotifyPropertyChanged("People"
); }
        }
 
       
public void
LoadData()
        {
            client.GetPeopleCompleted += client_GetPeopleCompleted;
            client.GetPeopleAsync();
        }
 
       
void client_GetPeopleCompleted(object sender, PersonService.GetPeopleCompletedEventArgs
e)
        {
           
if (e.Error != null
)
            {
               
MessageBox
.Show(e.Error.ToString());
            }
           
else
            {
                People = e.Result;
            }
        }
 
 
       
public event PropertyChangedEventHandler
PropertyChanged;
       
private void NotifyPropertyChanged(String
propertyName)
        {
           
PropertyChangedEventHandler
handler = PropertyChanged;
           
if (null
!= handler)
            {
                handler(
this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

 

The last part is to modify the MainPage.xaml and update item template to point to the properties that belong to person class, namely last name and first name.

        <controls:Pivot Title="MY APPLICATION">
            <!–Pivot item one–>
            <controls:PivotItem Header="first">
                <!–Double line list with text wrapping–>
                <ListBox x:Name="FirstListBox" Margin="0,0,-12,0"
 
                       
ItemsSource="{Binding People}">
                    <ListBox.ItemTemplate>
                        <DataTemplate>
                          <StackPanel Margin="0,0,0,17" Width="432">
                              <TextBlock
 
                                
Text="{Binding FirstName}"
 
                                
TextWrapping="Wrap"
 
                                
Style="{StaticResource PhoneTextExtraLargeStyle}"/>
                              <TextBlock
 
                                
Text="{Binding LastName}"
 
                                
TextWrapping="Wrap"
 
                                
Margin="12,-6,12,0"
 
                                
Style="{StaticResource PhoneTextSubtleStyle}"/>
                          </StackPanel>
                        </DataTemplate>
                    </ListBox.ItemTemplate>
                </ListBox>
            </controls:PivotItem
>

 

Now we will just call LoadData from the code behind of MainPage.  This is just a temporary fix, ordinarily I would have the view / view model hook up elsewhere.

    public partial class MainPage : PhoneApplicationPage
    {
       
// Constructor
        public
MainPage()
        {
            InitializeComponent();
 
            DataContext =
App
.ViewModel;
           
App.ViewModel.LoadData();
        }
    }

 

That was the last part.  Now we can run the phone application in the emulator.  And we should be able to see the list of two people that were inserted in Seed() method above.

To summarize, we just consumed WCF service from the phone.  To call the same from a deployed application, we will need to change the address in ServiceReference.ClientConfig file.  That is it.

The other part I would like to try is to insert a new person.  I am going to add a button to the second pivot item and call the insert method.  I am going to just use code behind, but you can look at my past posts on how do use MVVM Light to wire up commands.

            <controls:PivotItem Header="second"> 
                <Grid>
                    <Button
 
                      
Content="Insert Person"
 
                      
Click="Button_Click"
 
                      
Width="200"
 
                      
Height="100"/>
                </Grid>
            </controls:PivotItem
>

 

Here is the code in the view model that I need to add:

        public void InsertPerson()
        {
            client.AddPersonAsync(
new Person
() 
            { PersonID =
Guid.NewGuid(), FirstName = "John", LastName = "Johnson" });
        }

 

Here is the final code for my view model:

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using
WindowsPhonePivotAppWithData.PersonService;
 
 

namespace
WindowsPhonePivotAppWithData
{
   
public class MainViewModel : INotifyPropertyChanged
    {
        PersonService.
PersonServiceClient
client;
       
public
MainViewModel()
        {
            client =
new PersonService.PersonServiceClient
();
            client.AddPersonCompleted += client_AddPersonCompleted;
            client.GetPeopleCompleted += client_GetPeopleCompleted;
        }
 
       
private ObservableCollection<Person
> people;
 
       
public ObservableCollection<Person
> People
        {
           
get { return
people; }
           
private set { people = value; NotifyPropertyChanged("People"
); }
        }
 
       
public void
LoadData()
        {
 
            client.GetPeopleAsync();
        }
 
       
void client_GetPeopleCompleted(object sender, PersonService.GetPeopleCompletedEventArgs
e)
        {
           
if (e.Error != null
)
            {
               
MessageBox
.Show(e.Error.ToString());
            }
           
else
            {
                People = e.Result;
            }
        }
 
       
public void
InsertPerson()
        {
            client.AddPersonAsync(
new Person
() 
            { PersonID =
Guid.NewGuid(), FirstName = "John", LastName = "Johnson"
});
        }
 
       
void client_AddPersonCompleted(object sender, AsyncCompletedEventArgs
e)
        {
           
if (e.Error != null
)
            {
               
MessageBox
.Show(e.Error.ToString());
            }
           
else
            {
               
MessageBox.Show("Succecss adding person"
);
                client.GetPeopleAsync();
            }
        }
 
       
public event PropertyChangedEventHandler
PropertyChanged;
       
private void NotifyPropertyChanged(String
propertyName)
        {
           
PropertyChangedEventHandler
handler = PropertyChanged;
           
if (null
!= handler)
            {
                handler(
this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

 

And that is all there is to it.  We created a WCF service and consumed it from Windows phone application.  I used Entity Framework code first to create classes and I used the same classed as data contract for my service.  In the next post of this short series I will work on consuming a custom OData service.

Post to Twitter

Selecting Comma Delimited Data From SQL Server

Today I had to accomplish the following task.  I had to create a report that selects data from primary table and also selects data from a related table , comma delimited into a column on a report.  I keep bumping into this problem periodically, but always have to research the solution.  Today I am documenting the solution. 

Example

I have the following database on my SQL Server:

USE [master]

GO

/****** Object:  Database [RolodexEFCtp]    Script Date: 01/17/2011 20:37:17 ******/

CREATE DATABASE [RolodexEFCtp] ON  PRIMARY

( NAME = N’RolodexEFCtp’, FILENAME = N’C:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\DATA\RolodexEFCtp.mdf’ , SIZE = 2304KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB )

 LOG ON

( NAME = N’RolodexEFCtp_log’, FILENAME = N’C:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\DATA\RolodexEFCtp_log.LDF’ , SIZE = 504KB , MAXSIZE = 2048GB , FILEGROWTH = 10%)

GO

ALTER DATABASE [RolodexEFCtp] SET COMPATIBILITY_LEVEL = 100

GO

IF (1 = FULLTEXTSERVICEPROPERTY(‘IsFullTextInstalled’))

begin

EXEC [RolodexEFCtp].[dbo].[sp_fulltext_database] @action = ‘enable’

end

GO

ALTER DATABASE [RolodexEFCtp] SET ANSI_NULL_DEFAULT OFF

GO

USE [RolodexEFCtp]

GO

/****** Object:  Table [dbo].[Companies]    Script Date: 01/17/2011 20:37:19 ******/

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

CREATE TABLE [dbo].[Companies](

      [CompanyId] [int] IDENTITY(1,1) NOT NULL,

      [CompanyName] [nvarchar](40) NOT NULL,

      [DateAdded] [datetime] NOT NULL,

PRIMARY KEY CLUSTERED

(

      [CompanyId] ASC

)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]

) ON [PRIMARY]

GO

 

/****** Object:  Table [dbo].[CompanyContacts]    Script Date: 01/17/2011 20:37:19 ******/

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

CREATE TABLE [dbo].[CompanyContacts](

      [CompanyContactId] [int] IDENTITY(1,1) NOT NULL,

      [FirstName] [nvarchar](30) NOT NULL,

      [LastName] [nvarchar](50) NOT NULL,

      [CompanyId] [int] NOT NULL,

PRIMARY KEY CLUSTERED

(

      [CompanyContactId] ASC

)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]

) ON [PRIMARY]

GO

/****** Object:  ForeignKey [Company_Contacts]    Script Date: 01/17/2011 20:37:19 ******/

ALTER TABLE [dbo].[CompanyContacts]  WITH CHECK ADD  CONSTRAINT [Company_Contacts] FOREIGN KEY([CompanyId])

REFERENCES [dbo].[Companies] ([CompanyId])

ON DELETE CASCADE

GO

ALTER TABLE [dbo].[CompanyContacts] CHECK CONSTRAINT [Company_Contacts]

GO

 

In the database above I would like to select company name in one column and semi-colon delimited list of employees.  Something like:

image

I am going to accomplish this task by using XML functionality of SQL Server, specifically FOR XML clause.

Here is what my select looks like that accomplish this task:

SELECT Companies.CompanyName,

      STUFF(

            (SELECT ‘; ‘ + CompanyContacts.LastName + ‘, ‘ + CompanyContacts.FirstName

                  FROM CompanyContacts

                  WHERE CompanyContacts.CompanyId = Companies.CompanyId

                  FOR XML PATH()), 1, 1, ) As AllContacts

FROM Companies

ORDER BY Companies.CompanyName

 

 

 

You can of course customize contacts query in a number of ways, sorting and filtering that data.  Primarily, I want to illustrate that you can accomplish seemingly hard task with a single query.

Thanks.

Post to Twitter

My Applications in App Store for Windows Phone 7

I checked the download statistics of my applications for Windows Phone 7 in the App Store, and to my surprise I have quite a few downloads!  Mr.  Fortune’s Famous Quotes is a free application that generates a random famous quote on demand, accompanied by a cool animation effect.  As you can see, that application has been downloads 242 times between 12/29/2010  and 1/3/2011.  I published it on 12/29/2010.  Apparently, Windows phone users like quotes.  On top of that, my paid application ($0.99 total cost) – Sport Timer, was downloaded once, which technically infinity times better result than I expected.  This is pretty cool app, actually.  It allows you to enter multiple people, multiple events, includes stop watch, and maintains history of all recorded times.  It provides text view and graph view of results for each person/even type combination.

 

Here is the screenshot with stats from the App Hub.

image

Post to Twitter

Windows Phone 7 Controls Project Update

I have published an update to the calendar control on my CodePlex project dedicated to building common controls for Windows Phone 7.

I added a number of new features.  The biggest improvement added is the ability to use context menu from Silverlight Toolkit for Windows Phone 7.  In order to provide this feature, I added style property to Calendar control that allows you to specify a custom template for calendar item.  Of course, you have to be careful not to override parts of the template that are responsible for providing color information for the calendar.  Namely, in your template you have to have TemplateBinding for Foreground and Background.  Other than that, you can modify the default template as you see fit.  Then, you can set CalendarItemsStyle property on the calendar to force it to use different template.  Here is the example of the XAML for the screen that adds context menu to the calendar items.  As you see below I specify style for CalendarItem in the resources of the page, then use this style and assign it to CalendarItemStyle property of the calendar control.

<phone:PhoneApplicationPage 
  
x:Class="Sample.MainPage"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
   xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
   xmlns:controls="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls"
   xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
   xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 
  
xmlns:wi="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
    
  
xmlns:i="clr-namespace:Microsoft.Practices.Prism.Interactivity;assembly=Microsoft.Practices.Prism.Interactivity"
 
  
xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"
   xmlns:mvvmLight="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WP7"
   xmlns:wpControls="clr-namespace:WPControls;assembly=WPControls"
   mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="768"
 
  
FontFamily="{StaticResource PhoneFontFamilyNormal}"
   FontSize="{StaticResource PhoneFontSizeNormal}"
   Foreground="{StaticResource PhoneForegroundBrush}"
   SupportedOrientations="Portrait"  Orientation="Portrait"
   shell:SystemTray.IsVisible="True">
    <phone:PhoneApplicationPage.Resources>
        <Style TargetType="wpControls:CalendarItem" x:Key="ItemStyle">
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate  TargetType="wpControls:CalendarItem">
                        <Grid x:Name="OuterGrid" HorizontalAlignment="Stretch"
 

VerticalAlignment="Stretch">
                            <Border
 
                          
BorderThickness="2"
                           HorizontalAlignment="Stretch"
                           VerticalAlignment="Stretch"
                           BorderBrush="{StaticResource PhoneForegroundBrush}">
                                <Grid Height="60" HorizontalAlignment="Stretch"
 

VerticalAlignment="Stretch" >
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="Auto"/>
                                        <RowDefinition Height="*"/>
                                    </Grid.RowDefinitions>
                                    <Rectangle Grid.RowSpan="2"
 

x:Name="BackgroundRectangle" Fill="{TemplateBinding Background}" />
                                    <TextBlock
 
                                  
x:Name="DayNumberBlock"
                                   Text="{Binding Path=DayNumber,
 

RelativeSource={RelativeSource TemplatedParent}}" 
                                  
Foreground="{TemplateBinding Foreground}"
 
                                  
FontWeight="ExtraBold"
                                   HorizontalAlignment="Left"
 
                                  
VerticalAlignment="Top"
 
                                  
Margin="4,2,0,0"/>
 
                                </Grid>
                            </Border>
                            <toolkit:ContextMenuService.ContextMenu>
                                <toolkit:ContextMenu>
                                    <toolkit:MenuItem Header="Mark">
                                        <wi:Interaction.Triggers>
                                            <wi:EventTrigger EventName="Click">
                                                <mvvmLight:EventToCommand
 

Command="{Binding Path=MarkCommand, Mode=OneWay}" 

CommandParameter="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ItemDate}" />
                                            </wi:EventTrigger>
                                        </wi:Interaction.Triggers>
                                    </toolkit:MenuItem>
                                    <toolkit:MenuItem Header="Clear">
                                        <wi:Interaction.Triggers>
                                            <wi:EventTrigger EventName="Click">
                                                <mvvmLight:EventToCommand
 

Command="{Binding Path=ClearCommand, Mode=OneWay}" 

CommandParameter="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=ItemDate}" />
                                            </wi:EventTrigger>
                                        </wi:Interaction.Triggers>
                                    </toolkit:MenuItem>
                                </toolkit:ContextMenu>
                            </toolkit:ContextMenuService.ContextMenu>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </phone:PhoneApplicationPage.Resources>
 
    <!–LayoutRoot is the root grid where all page content is placed–>
    <Grid x:Name="LayoutRoot" Background="Transparent">
        <!–Pivot Control–>
        <controls:Pivot Title="Sample">
 
            <controls:PivotItem Header="calendar">
                <Grid>
                    <wpControls:Calendar x:Name="mainCalendar"
 
                                       
SelectedDate="{Binding Path=SelectedDate, Mode=TwoWay}"
 
                                       
CalendarItemStyle="{StaticResource ItemStyle}"
                                        DatesSource="{Binding Path=Dates}"
                                        ColorConverter="{Binding}"/>
                </Grid>
 
            </controls:PivotItem>
 
            <controls:PivotItem Header="other">
                <Grid>
 
                </Grid>
            </controls:PivotItem>
        </controls:Pivot>
    </Grid>
 

 
</phone:PhoneApplicationPage
>

 

To make this XAML work, you have to also add references to MVVM Light framework for the phone in addition to Silverlight toolkit for the phone.  ViewModel is very simple, but I want to paste entire code to make it very clear how it is used.

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows.Media;
using GalaSoft.MvvmLight.Command;
using PeriodTracker.ViewModels;
using
WPControls;
 
 

namespace
Sample
{
   
public class MainViewModel : INotifyPropertyChanged, IDateToBrushConverter
    {
       
public
MainViewModel()
        {
            Dates =
new ObservableCollection<ISupportCalendarItem
>();
            Dates.Add(
new DateInfo() { CalendarItemDate = DateTime
.Today });
            Dates.Add(
new DateInfo() { CalendarItemDate = DateTime
.Today.AddDays(1) });
            MarkCommand =
new RelayCommand<object
>(OnMark);
            ClearCommand =
new RelayCommand<object
>(OnClear);
        }
 
       
public RelayCommand<object> MarkCommand { get; set
; }
       
public void OnMark(object
item)
        {
           
if (!Dates.Where(one => one.CalendarItemDate == (DateTime
)item).Any())
            {
                Dates.Add(
new DateInfo() { CalendarItemDate = (DateTime
)item });
            }
        }
 
       
public RelayCommand<object> ClearCommand { get; set
; }
       
public void OnClear(object
item)
        {
           
ISupportCalendarItem info = Dates.FirstOrDefault(one => one.CalendarItemDate == (DateTime
)item);
           
if (info != null
)
            {
                Dates.Remove(info);
            }
        }
 
       
private DateTime
selectedDate;
 
       
public DateTime
SelectedDate
        {
           
get { return
selectedDate; }
           
set { selectedDate = value; NotifyPropertyChanged("SelectedDate"
); }
        }
 
       
public event PropertyChangedEventHandler
PropertyChanged;
       
private void NotifyPropertyChanged(String
propertyName)
        {
 
           
if (PropertyChanged != null
)
            {
                PropertyChanged(
this, new PropertyChangedEventArgs
(propertyName));
            }
        }
 
       
private ObservableCollection<ISupportCalendarItem
> dates;
 
       
public ObservableCollection<ISupportCalendarItem
> Dates
        {
           
get { return
dates; }
           
set { dates = value; NotifyPropertyChanged("Dates"
); }
        }
 
       
public Brush Convert(DateTime dateTime, bool isSelected, Brush defaultValue, BrushType
brushType)
        {
           
if (brushType == BrushType
.Background)
            {
               
if (Dates != null
&& Dates.Where(one => one.CalendarItemDate == dateTime).Any() && !isSelected)
                {
                   
return new SolidColorBrush(Colors
.Red);
                }
               
else
                {
                   
return
defaultValue;
                }
            }
           
else
            {
               
if (Dates != null
&& Dates.Where(one => one.CalendarItemDate == dateTime).Any() && isSelected)
                {
                   
return new SolidColorBrush(Colors
.Red);
                }
               
else
                {
                   
return defaultValue;
                }
            }
        }
    }
}

 

As you can see, I have a property that provides source with dates to the calendar.  This is also new in this release.  If you provide an Observable Collection where each item implements new interface ISupportCalendarItem, calendar can improve overall performance.  It also enables you not to explicitly raise property changed events, forcing control to repaint.  Having said that, you now have two ways to explicitly force repaint of the calendar.  You can call Refresh() method on it.  Or, in your view model you can raise property changed event for the property that is bound to the DatesSource property of the calendar.

Another change I introduce is consolidate date to brush converters into a single class.  This minimizes the code you have write as well as simplifies XAML at the same time.  Here is the new interface:

using System.Windows.Media;
using
System;
 

namespace
WPControls
{
   
/// <summary>
    /// This converter can be used to control day number color and background color
    /// for each day
    /// </summary>
    public interface IDateToBrushConverter
    {
       
/// <summary>
        /// Perform conversion of a date to color
        /// This can be used to color a cell based on a date passed it
        /// </summary>
        /// <param name="dateTime">Date for the calendar cell</param>
        /// <param name="isSelected">Indicates if a date is selected by the user</param>
        /// <param name="defaultValue">Brush that will be used by default
        /// if the converter did not exists
        /// </param>
        /// <param name="brushType">Type of conversion to perform – foreground or background</param>
        /// <returns>New Brush to color day number or calendar cell background</returns>
        Brush Convert(DateTime dateTime, bool isSelected, Brush defaultValue, BrushType brushType);
    }
}

 

Brush type is the enumeration that consists of background and foreground:

namespace WPControls
{
   
/// <summary>
    /// Type of brush to driver color converter
    /// </summary>
    public enum BrushType
    {
       
/// <summary>
        /// Calendar item background conversion
        /// </summary>
        Background,
       
/// <summary>
        /// Day number of calendar item
        /// </summary>
        Foreground
    }
}

 

This concludes the list of changes in this release.  Please let me know if you have any questions at all regarding the use of the control

Post to Twitter

Windows Phone 7 Project

I started new CodePlex project for controls for Windows Phone 7.  One control I needed for my next application is calendar control.  I could not find one, so I started thinking about one a little while ago.  Today I published an alpha version of calendar control.  You can find it here http://wpcontrols.codeplex.com/.

Calendar control supports the following features in the initial release:

  • Next/Previous month buttons
  • Ability to provide converters to color day number or date cell background
  • Ability to select a date and apply background color
  • Data binding to SelectedDate

Calendar also supports the following events

  • MonthChanging is fired before calendar is rebuilt for the next month. Can be used to setup data for converters
  • MonthChanged is fired after calendar is rebuilt for new month/year
  • SelectionChanged is fired when a user selects a date

As part of download, you are provided with a working sample that shows how to do converters and calendar control without converters.

Here is the markup you can use in both cases:
Sample calendar control:

xmlns:wpControls="clr-namespace:WPControls;assembly=WPControls"
<wpControls:Calendar x:Name="Cal"/>

 

 


Using converters:

    <phone:PhoneApplicationPage.Resources>

        <local:BackgroundConverter x:Key="BackgroundConverter"/>

        <local:DayNumberConverter x:Key="DayNumberConverter"/>

    </phone:PhoneApplicationPage.Resources>

<wpControls:Calendar      x:Name="Cal"
    BackgroundConverter="{StaticResource BackgroundConverter}"
    ForegroundConverter="{StaticResource DayNumberConverter}"
    MonthChanged="Cal_MonthChanged"
    MonthChanging="Cal_MonthChanging"
    SelectionChanged="Cal_SelectionChanged"
    />

Converter simply have to implement a simple interface with one method:

image

Of course, instead of hard-coded date you can drive them based off your data on the phone.  On a second note, if you need a simple, easy to use, yet powerful database for your Windows Phone 7 application, check out my other project on CodePlex: http://winphone7db.codeplex.com/

Here is what the control looks like on the phone:

CalendarControl.png

Post to Twitter

MVP 2011

I got my Happy New Year present from Microsoft this morning.  They gave me Microsoft MVP award for the second year in a row.  I feel honored and humbled that my efforts in promoting Microsoft technology are appreciated.  I will continue doing my best in showcasing great technologies that Microsoft puts out year in and year out.

Happy New Year, everybody!

Post to Twitter

Pitfalls of Deploying Silverlight Applications in Web Farms

I wanted to make a few notes regarding my recent experience of deploying a Silverlight application in web farm environment.  Here is what the topology looked like.  It included load balancer appliance configured to redirect the traffic to one of three servers.  There was also SQL Server cluster in active-passive configuration.  The application was using 3 different databases.  There was also SSRS component deployed on the same instance(s) of SQL Server, since Silverlight application included report viewer built using SSRS Report Viewer for Web Forms.  The viewer was hosted in an ASPX page that contains SSRS Report Viewer.  The page itself was hosted inside a Silverlight window that contained Telerik’s HtmlPlaceholder control.

The first problem that we encountered was MSDTC.  We use TransactionScope to ensure transactional integrity of data updates.  Unfortunately, since we have multiple databases in some updates, TransactionScope will automatically promote all transactions to MSDTC.  We got errors from MSDTC right away.  We had to configure MSDTC on each of the server in the SQL cluster.  In cluster environment in Component Services you have to actually expand cluster node and configure MSDTC from there.  You have to enable network access.  We set it up with no authentication since all machines that participate in each transaction are not on the same domain, so configuring authentication for MSDTC would be pretty hard.  We also had to configure MSDTC on all application servers that house our WCF services that Silverlight application is using.  Event after all that MSDTC did not work.  We also had to put exceptions into two different firewalls that production environment deployed.  Once that was done, MSDTC finally worked.

The next set of errors came from report viewer.  We kept getting invalid view errors.  Of course, since I do not deploy production applications every month, I forgot about view state.  Silverlight does not care about that, but SSRS Viewer does!  So, first step was to synchronize machine keys for all web servers in our environment.    You can read more about machine keys here.  You can use this little program to generate keys on the fly.  Once that was done, I was expecting SSRS to work.  However, I was still getting errors.  Again, it had everything to do with web farms.  I forgot that I also need to synchronize session state.  I had to configure web applications to use SQL Server based session state.  First, you have to enable session state on an SQL Server you are going to use.  You can use aspnet_regsql.exe tool that ships with .NET to do so.  You can run it from any machine, and simply point to SQL Server.  You can read about this tool in this article on MSDN.  The last step is to update web.config files on all our web servers to looks similar to the following.  Your syntax will vary depending on version of IIS you use and how your application pool is configured (classic or integrated pipeline mode) in IIS 7+.  You can read more about the session node here.  Here is an example of the configuration.

 

<sessionState
    mode="SQLServer"
    sqlConnectionString="data source=<SQL Server Name or IP address>;
        user id=<User ID>;password=<Password>"
    cookieless="false"
    timeout="20"
    />

Timeout is in minute.  20 minutes is the default, and you can change it if you would like.

OK, these are the steps we had to take to deploy the app.  As always, I try to make notes my blog to document my experiences to hopefully make my next deployment task easier.  I always encourage developers to maintain a blog for this exact reason.  Your own blog becomes your personal knowledge base.

Post to Twitter

Maximum Number of Concurrent Connections in Internet Explorer

Today as I was debugging and optimizing a Silverlight application, I discovered a hidden feature in IE 8 that allows you to increase the number of concurrent connections to any server.  Here is the link that describes the procedure.

http://msdn.microsoft.com/en-us/library/cc304129(VS.85).aspx

You can try to speed up your browser by changing this setting.

Post to Twitter

How do Determine if Your Application is Running in Cassini

This is really short post, more a tip.

If you need to determine if your application is running in IIS or Developer Web Server (Cassini) that comes with Visual Studio, you can test the process name you are running in.  For example, the following code:

System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName

will return the name of the running process.  In case of developer web server in Visual Studio 2010 it returns

"C:\\Program Files\\Common Files\\Microsoft Shared\\DevServer\\10.0\\WebDev.WebServer40.exe"

So, if you for example want to scan Bin folder, code that you run in IIS will not work running in Cassini.  This simple one line of code will let you know what you are running.

Post to Twitter

Blog Stats

I moved my blog to this site in November 2009, a little over a year ago.  I did that based on an advice of fellow programmer, urging me to find a domain that is easier to remember and spell than SergeyBarskiy.Windows.Live.com. Of course, blogging was recently removed from features of Windows Live and transferred to a third party.  So, there came www.DotNetSpeak.com.  It took a few hours to try to find a domain name that was not taken that had a way to convey my programming interests.

Today I checked the stats, and my blog had over 50,000 views in a little over a year!  Woo-hoo!  Here is a screenshot of the stats

image

Thank you, everyone.  I never thought that my posts would attract that much attention.  Either that of my dad is really active on the internet Smile.

On another note, I often use my own blog as a source of information.  I try to blog about all interesting work that I do, and I encourage everyone to do the same.  Chances are, if you did some work in the past, you are likely to encounter similar circumstances later.  Wouldn’t be nice to just search your own blog and find an answer in a minute.

 

Happy Holidays, everybody!

Post to Twitter

Building Windows Phone 7 Silverlight Application

It this post I want to describe the process I went though building and publishing my first Silverlight application for Windows Phone 7.  It is currently being tested, and I hope I will pass the test this time.  I went through a couple of iterations of testing already, learning in the process from my mistakes.  I want to describe the process so that I myself can remember the steps, but hopefully help other folks with some tips and tricks.

In order to be able to publish an application for Windows Phone 7, you must sign up as a developer on App Hub – http://create.msdn.com.  This process was pretty painless actually, and only took a few minutes.  A couple of important things to remember.  Once you sign up, you will get an email from GeoTrust.  You have to follow the link in the email and answer a few questions confirming your identity.  The questions for me came from my credit report.  This tells me that Microsoft really wants to ensure there is a real person behind the signee.  Once you complete this step, you have to go back to App Hub and fill out your bank account information.  Once you are done with paperwork, you are ready to start writing your application.

To create an app, you have to have some tools installed on your machine.  You have to have at lest Visual Studio Express for Windows Phone, but I would also recommend Expression Blend for Windows Phone 7.  You can find the links to the software on main page of App Hub.

Once you have basic tools, you will likely need some secondary software to help you write your applications.  Here is what I would recommend.

  • Windows Phone 7 Toolkit from CodePlex.  Controls in the toolkit are written by Microsoft folks just like Silverlight toolkit.  You can download the toolkit here  To help you get started, check out Tim Heuer’s post on the toolkit here.
  • Another good tool is version of Prism for Windows Phone 7.  This article on MSDN describes the content of Prism for the phone.  You can download binaries here.  Once you build Prism 4, you will find Phone folder under Bin with all the binaries.  There is a lot of cool functionality there.
  • I had some troubles getting commanding to work using blend using event to command behavior.  As a result, I also downloaded and used MVVM Light by Laurent Bugnion.  You can download binaries and find some quick start links on CodePlex here.
  • If you want to save some data on the phone, I would recommend using a database abstraction by your truly.  You can download Database for Windows Phone 7 here.

Now, some sample code.

Application bar is the portion of the screen that shows the menu.  I am using Prism to implement commands to react to user interactions.  Here is XAML portion of the application bar.

<phone:PhoneApplicationPage
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
   xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
   xmlns:controls="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls"
   xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
   xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 
  
xmlns:wi="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
    
  
xmlns:i="clr-namespace:Microsoft.Practices.Prism.Interactivity;assembly=Microsoft.Practices.Prism.Interactivity"
 
  
xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"
   xmlns:mvvmLight="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WP7"
   xmlns:charting="clr-namespace:System.Windows.Controls.DataVisualization.Charting;

assembly=System.Windows.Controls.DataVisualization.Toolkit"
   x:Class="SportTimer.MainPage"
 
  
mc:Ignorable="d" d:DesignWidth="480" d:DesignHeight="696"
 
  
FontFamily="{StaticResource PhoneFontFamilyNormal}"
   FontSize="{StaticResource PhoneFontSizeNormal}"
   Foreground="{StaticResource PhoneForegroundBrush}"
   SupportedOrientations="Portrait"  Orientation="Portrait"
   shell:SystemTray.IsVisible="True">
 
    <!–Sample code showing usage of ApplicationBar–>
    <phone:PhoneApplicationPage.ApplicationBar>
        <shell:ApplicationBar IsVisible="True" IsMenuEnabled="True">
            <shell:ApplicationBarIconButton IconUri="/icons/clock.png" Text="time" />
            <shell:ApplicationBarIconButton IconUri="/icons/person.png" Text="people"/>
            <shell:ApplicationBarIconButton IconUri="/icons/event.png" Text="events"/>
            <shell:ApplicationBarIconButton IconUri="/icons/graph.png" Text="history"/>
        </shell:ApplicationBar>
    </phone:PhoneApplicationPage.ApplicationBar>
 
    <wi:Interaction.Behaviors>
        <i:ApplicationBarButtonCommand ButtonText="time" 

CommandBinding="{Binding ChangeIndexCommand, Mode=OneWay}" 

CommandParameterBinding="{Binding TimeIndex}"/>
        <i:ApplicationBarButtonCommand ButtonText="people" 

CommandBinding="{Binding ChangeIndexCommand, Mode=OneWay}" 

CommandParameterBinding="{Binding PeopleIndex}"/>
        <i:ApplicationBarButtonCommand ButtonText="events" 

CommandBinding="{Binding ChangeIndexCommand, Mode=OneWay}" 

CommandParameterBinding="{Binding EventIndex}"/>
        <i:ApplicationBarButtonCommand ButtonText="history" 

CommandBinding="{Binding ChangeIndexCommand, Mode=OneWay}" 

CommandParameterBinding="{Binding HisotryIndex}"/>
    </wi:Interaction.Behaviors>
    <!–LayoutRoot is the root grid where all page content is placed–>
    <Grid x:Name="LayoutRoot" Background
="Transparent">

 

Let me comment a bot on the code.  Application bar can have at most 4 buttons, and I am using all of them.  I am declaring application bar button command separately which is how Prism wants the implementation done, then bind commands to buttons via Text property of the button. Commands are declared in my view model as follows

 

        public DelegateCommand<object> ChangeIndexCommand { get; set; }        public void OnChangeIndex(object parameter)        {            SelectedPivotIndex = int.Parse(parameter.ToString());        }

 

ChangeIndexCommand = new DelegateCommand<object>(OnChangeIndex);

I am creating an instance of the command in view model constructor.  The command simply changes selected index of the pivot control,

I also have some button controls in my application.  I use MVVM light for those, again because I could not get Prism behavior to work.

<Button Content="Stop" Grid.Row="3" Grid.Column="2">    <wi:Interaction.Triggers>        <wi:EventTrigger EventName="Click">            <mvvmLight:EventToCommand Command="{Binding Path=StopTimerCommand}" />        </wi:EventTrigger>    </wi:Interaction.Triggers></Button>

 

Another interesting control I use is ContextMenu from toolkit.  I am using it to delete items from ListBox:

<ListBox x:Name="FilteredHistoryListBox" Grid.Row="3" Grid.ColumnSpan="3"

           ItemsSource="{Binding Path=FilteredHistory}">

    <ListBox.ItemTemplate>

        <DataTemplate>

            <Border Margin="0" BorderThickness="0" Background="Transparent" Padding="0">

                <toolkit:ContextMenuService.ContextMenu>

                    <toolkit:ContextMenu>

                        <toolkit:MenuItem Header="Delete">

                            <wi:Interaction.Triggers>

                                <wi:EventTrigger EventName="Click">

                                    <mvvmLight:EventToCommand 

Command="{Binding ElementName=EventsItem, Path=DataContext.DeleteHistoryCommand, Mode=OneWay}" 

CommandParameter="{Binding}" />

                                </wi:EventTrigger>

                            </wi:Interaction.Triggers>

                        </toolkit:MenuItem>

                    </toolkit:ContextMenu>

                </toolkit:ContextMenuService.ContextMenu>

                <StackPanel Margin="0,0,0,7">

                    <TextBlock Text="{Binding Path=TimeString}"  

TextWrapping="NoWrap" Margin="12,0,0,0" Style="{StaticResource PhoneTextExtraLargeStyle}"/>

                    <TextBlock Text="{Binding Path=HistoryDateString}" TextWrapping="NoWrap" Margin="12,-6,0,0" Style="{StaticResource PhoneTextSubtleStyle}"/>

                </StackPanel>

            </Border>

        </DataTemplate>

    </ListBox.ItemTemplate>

 

 

Now, about application bar icons.  I was trying to use the icons from Visual Studio, and I failed the test.  Then, I actually read the documentation Smile

The application bar icons must be 48×48 pixels with transparent background, with the icon itself (image or text) white 24×24 pixels.  I found this very good post by Brad Tutterow, and I used it to create custom icons for my application.  Nothing fancy, but my skill were good enough to create four icons for my Sport Timer application.   Make sure to test your application in light theme either on the phone or emulator.  Here is my person icon and graph icon.

Persongraph

I wanted to incorporate graphs info my application, and I found this great port of chart library from Silverlight toolkit.  At least I think that is what it is.  Here is the link to the post about it that includes download link.

Another tip that I have is that for some reason virtual keyboard did not work on one of my screens.  Come to find out through trial and error that you must inherit for PhoneApplicationPage for that to work.  I used UserControl, following typical Silverlight development pattern.  Once I changed the inheritance in XAML and .cs files, everything worked like magic.

Also, you have to test your icons on the phone.  Make sure to pin your application to start up to ensure it looks good.  You can setup icons and test for start up page on the phone and regular list on the phone in properties of your application page.  Make sure to check these settings.

image

You can use the same image or different ones.  I followed the default application and used different sizes.  You can see the image size from the icon name.  All of them are images in png format.

When you submit your application, you are also required to submit a number of image in specific format.  I used Paint.NET to resize my images and set DPI.  You can do both through Resize command window.  Also, make sure the screenshots of your application do not include the emulator itself, only the application.  You will fail testing because of the this as well.  Again, follow the descriptions in submission page to verify the DPI and sizes of all your images.

I hope this post may save a few folks a few extra minutes.

Post to Twitter

Entity Framework CPT 5 – Cont.

Continuing with previous post, I wanted to go over data annotations, some old and some new in CTP 5.  Of course, everything you can do with data annotations, you can do with fluent API.  Once important this to remember about data annotations is that they are used for validation as well as defining columns in database.  All data annotations are implemented as attributes.  Here are some of the attributes to remember.  Each class defines a table in the database of course.  Attributes can be used to decorate a class, by primary are used to decorate class property that become columns in a database.

  • [Key] – specified which column or columns comprise a primary key for a table.
  • [StringLength] – specifies maximum length, and optionally minimum length.  Minimum length is only used for validation, not database constraints.
  • [MaxLength] – can be used instead of StringLenth to specify maximum length for a column
  • [ConcurrencyCheck] – flags columns that participate in optimistic concurrency checks.
  • [Required] – specifies that a value is required for a property.  Column is flagged as not nullable.
  • [Timestamp] – flags time stamp columns that are typically used for concurrency checks
  • [Column] – can be used to specify a column name.  If omitted, property name becomes column name.  You can also use this attribute to control ordinal position of a column.
  • [Table] – can be used to specify a table name.  If omitted, class name becomes table name.
  • [DatabaseGenerated] can be used to signal that a data is populated via a database.  Possible values are Computed, Identity or None.  None is the default.
  • [NotMapped] added in this release.  Allows you to have a property in a class without generating a column in a database.
  • [ForeignKey] and [InverseProperty] are used for foreign key columns

 

This release also included pluggable conventions preview.  Conventions control various aspects of behavior of code first entity framework release.  For example, pluralization of table names.  You can also write your own conventions and attributes to control behavior of the entity framework.  This is extremely powerful feature that pretty much allows you to customize database generation to unlimited extent.

Post to Twitter

New Releases for ASP.NET MVS 3 and Entity Framework CTP

Since I posted my last blog on building ASP.NET MVC 3 application using Razor view engine and Entity Framework code first CTP 4, both of these technologies underwent updates.  Both are covered on Scott Guthrie’s blog.  You can read MVC 3 RC 2 announcement. and Entity Framework CTP 5 announcement.

In this post I will cover the change I had to make to compile my existing project.  Frist of all, I downloaded and installed both updates.  Here is the download link to EF CTP 5.  This link points to MVC 3 download.

Once I downloaded and installed both, I had a slew of compiler errors.  View property of the controller and VIew property of the VIew are now called ViewBag.  It is dynamic type property and you use the following syntax to access it:

this.ViewBag.Message = "Welcome to ASP.NET MVC!";

Similar syntax is used in views:

@{
    ViewBag.Title = "About Us";
}

 

This was the major change, but it was fairly mechanical. 

Entity framework changes were simple as well.  Database classes is now called DbDatabase to match other naming conventions.  Class that controls if database is recreated when model changes is now called DropCreateDatabaseIfModelChanges. Once these few changes were done I was able to run the application again.  You can download updated application here.

You can see full list of change in MVC RC 2 here.

List of changes to Entity Framework going to CTP 5 is available in ReadMe file on the download page I pointed to above.  I am going to highlight the key points below.  These are applicable to code first as a whole, not necessary to CTP 5 itself.

  • T4 templates for code first classes are included.  As a result, you can reverse engineer a model first or database first models into a set of DbSet/DbContext classes.  If you have existing database, and you want to switch to use code first approach, the process is very simple.
  • You have access to entity states (Added, Unchanged, Modified, Deleted) and property values for each property values.  Here is how you can access entity state and property values
context.Entry<BlogEntry>(entry).State = System.Data.EntityState.Unchanged;
var text = context.Entry<BlogEntry>(entry).OriginalValues["PostText"];
var newText = context.Entry<BlogEntry>(entry).CurrentValues["PostText"];

 

  • There is ability to explicitly load navigation property’s data.
context.Entry<BlogEntry>(entry).Collection<BlogCategory>().Load()

 

  • You have a property that returns ObservableCollection for a set of entries.  This is useful in WPF applications.

ObservableCollection<BlogEntry> collection = context.Entries.Local;

  • You can get data without tracking which reduces the overhead of getting the data.  You have to import System.Data.Entity namespace
var data = blogs.Skip((currentPage - 1) * pageSize).Take(pageSize).AsNoTracking().ToArray();

 

  • There is a lot of change information available from context.ChangeTracker property.
  • You can execute raw SQL Commands.  Those are accessible through context.Database.SqlCommand (akin to ExecuteNonQuery) and context.Database.SqlQuery and context.Database.SqlQuery<T> both akin to ExecuteQuery and return a collection of objects based on type you specify.  You are not responsible for materializing the results of this queries, which is pretty cool.
  • If you do not want to use EdmMetadata table which is used to detect changes to model that database cannot accommodate, you can turn this off by removing a convention from model builder.
modelBuilder.Conventions.Remove<IncludeMetadataConvention>();

 

I am going to cover more changes in the next post.

 

Post to Twitter

Silverlight 5

Today I am going to make an attempt to analyze new features in Silverlight 5.0 and see how they fit into full picture of Microsoft efforts and their announcements regarding Silverlight and HMTL 5.

You can see full list on Scott Guthrie’s blog here.  You can also read some more comments by John Papa here.  You can watch keynote here.

First of all, multimedia experience in Silverlight 5 further enhances great abilities of Silverlight.  Setting up live streaming is very easy in IIS 7.  Also, performance of playback will be improved.  All-in-all, we all already knew that Silverlight is great for media.  I am a lot more interested in business applications though.

One of my biggest pet peeves is productivity.  I am glad to see that Microsoft is paying attention to develop experience.  Debugging on data binding errors in XAML via breakpoints is pretty neat.  Having said that, binding errors are already echoed to the output window today.  Default data templates can be setup for a specific type.  This feature is super cool to me.  I can just put my business object into XAML and it will be automatically resolved via data template and UI will be created for it.  I can see that MVVM frameworks will add support for something like that to enable more transparent resolution of data into visuals.  You will also be able to use data binding in styles’ property setters.  This makes styles ever more powerful.  There will be DataContextChanged event added.  I have been missing this event ever since I started with Silverlight.  One has to always play tricks to create controls that need to update themselves when their data context changes.  Those tricks will no longer be needed.  Markup extensions will be supported for properties and event handlers.  As a result, you can create markup extensions methods that will for example just invoke a method on a view model without having to always create a command.  This will make you more productive, saving you from having to write boiler plate code over and over.  Ancestor type relative source will allow data binding of data template properties to the control properties that this data template support.

There are improvements in WCF stack and FCW RIA services.  WS-Trust  will be supported.  There will be better support for complex types in RIA services, providing more comprehensive abilities for complex business scenarios.  Silverlight 5 network stack will also have support for low-latency scenarios, such as frequent (almost-live) updates. 

There is a number of improvement regarding text presentation.  Multi-line text that flows around other visuals, clearer typography, just to name a few.  Printing is finally better.  You will have PostScript vector printing API will provide support for complex documents and reports.  Layout transitions make building appealing interfaces much simpler.  Text layout performance is greatly improved.  Double-click event will be there.

Silverlight 5 will enable 3D GPU accelerated rendering.  This may not be applicable for main stream line of business applications.

Out of browser support becomes literally awesome.  You can now have child windows that are undocked from main window.  They show up in Windows task bar as separate windows as well.  You can now have infinite real estate for you applications.  Also, you can now invoke WIn32 API directly from out-of-browser and in-browser.  If a policy is configures, you can literally export to Word using dynamics and launch Word with new document while in browser.  Users will have more control over sandboxing without compromising security.  You will also be able to access hardware devices by utilizing COM interop.  You can have better kiosk support via on screen keyboard in full screen mode.

64 bit Silverlight is coming.  This to me is a critical feature, and should have been there years ago.  I do not want to teach my users which browser to use for my app.  Now, it is not necessary.  Hardware acceleration will be available in windowless mode now.  This is a critical piece of general speed improvements.

Developer experience is further improved via Microsoft Visual Studio profiling support including CPU, memory, thread contention.

Now the summary.  Rumors of Silverlight death have been greatly exaggerated, and now this is pretty obvious.  Actions always speak louder then words, and SL 5 announcement by Scott Guthrie is something that community needed badly ever since Bob Muglia’s comment at PDC.

As you can see, Silverlight is getting performance improvements, productivity improvements, user experience improvements and media handling improvements.  The sandbox can be relaxed by users, enabling richer integration with Windows operating system.  Silverlight is even getting 3D.  What are the lessons learned from this announcement?  Here is my prioritized list:

  • Silverlight is alive and well and will be with us for many years to come.  Nobody should be afraid to use Silverlight platform for business applications.
  • Silverlight will be faster for users in version 5.
  • Silverlight will be even more productive environment in version 5.
  • Integration with Office and Windows will be better.  Now, this is bad news for WPF.  .

It appears to me that Microsoft is positioning Silverlight to be default de facto platform for line of business application.  I cannot say I disagree.  Rich applications developed faster and cheaper is what businesses need and Silverlight has.

 

Here is keynote.  Watch and enjoy.

Post to Twitter

Developing ASP.NET MVC 3 Application with EF CTP (Part 5)

In this post I will describe how to use MVC with a jquery grid control to display tabular data.  To start with, there is a number of grids available, some even integrate with ASP.NET MVC by providing an MVC assembly that generates the javascript for the grid.  One of these components in jqGrid.  I am not going to use MVC helper for this demo primarily because MVC component is not a free download.  As a result, I am going to just download jqGrid itself from this site.  One of the files in download is a text file that describes what script and CSS files you need to include in your project.  I am going to just include a screenshots of my project.  I am only using one theme – swanky-purse.

image

 

image

Now, we need to incorporate those scripts into my master page (_Layout.cshtml) so that I do not have to download them in each view:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<
html xmlns
="http://www.w3.org/1999/xhtml">
<
head>
    <title>@View.Title</title>
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery-1.4.1.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
    <link href="@Url.Content("~/Content/swanky-purse/jquery-ui-1.8.6.custom.css")" rel="stylesheet" type="text/css" />
    <link href="@Url.Content("~/Content/ui.jqgrid.css")" rel="stylesheet" type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery.ui.core.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.ui.datepicker.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/grid.locale-en.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.jqGrid.min.js")" type="text/javascript"></script
>
</
head
>
<
body>
    <div class="page">
        <div id="header">
            <div id="title">
                <h1>
                    My MVC Application</h1>
            </div>
            <div id="logindisplay">
                @Html.Partial("_LogOnPartial"
)
           
</div>
            <div id="menucontainer">
                <ul id="menu">
                    <li>@Html.ActionLink("Home", "Index", "Home")</li>
                    <li>@Html.ActionLink("About", "About", "Home")</li>
                    <li>@Html.ActionLink("Blogs", "Index", "Blogs")</li>
                </ul>
            </div>
        </div>
        <div id="main">
            @RenderBody()
           
<div id="footer">
            </div>
        </div>
    </div
>
</
body
>
</
html>
 

 

Now, we are going to plug in query grid script into the index page that shows blog entries – Blogs\Index.cshtml.  Here is the entire cshtml file:

@{
    View.Title = "Blogs";
    Layout =
"~/Views/Shared/_Layout.cshtml"
;
}

<h2>
    Index</h2
>
<
p>
    @Html.ActionLink("Create New", "Create")
</p
>
<
table id="blogsList" class="scroll" cellpadding="0" cellspacing
="0">
</
table
>
<
div id="blogsPager" class="scroll" style="text-align
: center;">
</
div>
 
<script type="text/javascript">
    $().ready(function
() {
        $(
"#blogsList"
).jqGrid({
            url:
‘./Blogs/BlogsGridData/’
,
            datatype:
‘json’
,
            mtype:
‘GET’
,
            colNames: [
'', '', 'Title', 'Posted On'
],
            colModel: [
            { name:
'Edit', index: 'Edit', width: 80, align: 'left', sortable: false
},
            { name:
'Delete', index: 'Delete', width: 80, align: 'left', sortable: false
},
            { name:
'Title', index: 'Title', width: 300, align: 'left'
},
            { name:
'PostedOn', index: 'PostedOn', width: 100, align: 'left'
}],
            pager: $(
‘#blogsPager’
),
            rowNum: 2,
            rowList: [2, 5, 10, 20, 50],
            sortname:
‘PostedOn’
,
            sortorder:
"desc"
,
            viewrecords:
true
,
            caption:
‘Blogs’
        });
    });

</script
>

 

Let me describe the most interesting settings here.  Url is the most notable one.  It will be used to return json data for the grid.  I know I need json because my datatype is set as such.  The actual Url will be intercepted by the routing in ASP.NET MVC to my Blogs controller’s BlogGridData method.  I will show it momentarily.  I will have 4 columns (colNames) – two without headers.  Those two columns with contain edit and delete links (anchors).  The colModel property describes the layout of the columns.  Pager property simply points to a div that will be formatted as pager control for my grid.  I also specify default sort column name and direction.  The entire grid will be attached to my table with the name of blogist (see HTML portion of the cshtml file above).

Next, let me show you what my BlogGridData looks like.  I will start with the code for entire method:

        /// <summary>
        /// Get Json data for the grid
        /// </summary>
        /// <param name="sidx">Column to osrt on.  Do not change parameter name</param>
        /// <param name="sord">Sort direction.  Do not change parameter name</param>
        /// <param name="page">Current page.  Do not change parameter name</param>
        /// <param name="rows">Number of rows to get.  Do not change parameter name</param>
        /// <returns></returns>
        public ActionResult BlogsGridData(string sidx, string sord, int? page, int
? rows)
        {
           
using (BlogContext context = new BlogContext
())
            {
               
int
pageSize = rows ?? 2;
               
int
totalRecords = context.Entries.Count();
               
int totalPages = (int)Math.Ceiling((float)totalRecords / (float
)pageSize);
               
int
currentPage = page ?? 1;
               
string sortByColumnName = sidx ?? "PostedOn"
;
               
string sortDirection = sord ?? "desc"
;
 
               
var blogs = (from one in
context.Entries
                            
select
one);
               
if (sortByColumnName == "PostedOn"
)
                {
                   
if (sortDirection.Equals("desc"
))
                        blogs = blogs.OrderByDescending(blog => blog.PostedOn);
                   
else
                        blogs = blogs.OrderBy(blog => blog.PostedOn);
                }
               
else
                {
                   
if ("desc"
.Equals(sortDirection))
                        blogs = blogs.OrderByDescending(blog => blog.Title);
                   
else
                        blogs = blogs.OrderBy(blog => blog.Title);
                }
               
var
data = blogs.Skip((currentPage – 1) * pageSize).Take(pageSize).ToArray();
 
               
var jsonData = new jqGridJson
()
                {
                    total = totalPages,
                    page = currentPage,
                    records = totalRecords,
                    rows = (
                     
from blog in
data
                     
select new jqGridRowJson
                      {
                          id = blog.BlogEntryId.ToString(),
                          cell =
new string
[] { 
                               
"<a href=’" + string.Format("./Blogs/Edit/{0}", blog.BlogEntryId.ToString()) + "’>Edit</a>"
,
                               
"<a href=’" + string.Format("./Blogs/Delete/{0}", blog.BlogEntryId.ToString()) + "’>Delete</a>"
,
                                blog.Title, 
                                blog.PostedOn.Value.ToShortDateString() }
                      }).ToArray()
                };
 
               
return Json(jsonData, JsonRequestBehavior.AllowGet);
            }
        }

 

As you can see, I am creating Url’s for edit and delete links.  One important thing to remember is that parameters to any method (BlogsGridData) will be automatically parsed from query string, so you cannot change their names.  The names are hard coded in jqGrid.  In the beginning of the method I am parsing out page size, current page, etc…  Them I am selecting the data from my blogs table.  More specifically, I am creating IQueryable<BlogEntry>, which is my blogs variable.  This query actually is not executed until I access results, which is the line in bold. So, there on that line I am constructing classes that will be later serialized using json serializer.  The classes are simply helper classes because jqGrid again expects the result set in certain format.  Here are those two helper classes:

    public class jqGridJson
    {
       
public int total { get; set
; }
       
public int page { get; set
; }
       
public int records { get; set
; }
       
public jqGridRowJson[] rows { get; set; }
    }

    public class jqGridRowJson
    {
       
public string id { get; set
; }
       
public string[] cell { get; set; }
    }

 

At the end, my last line returns JsonResult class.  That is all there is to using jqGrid with MVC 3.0.  One important note is that Url’s that point to Controller methods are relative.  It took me a while to figure out why they are not invoked in IIS, but with in web server in Visual Studio.  Here is the screenshot of the final version running in IIS:

image

Please let me know if you have any questions.  You can download full solution here.

 

Thanks.

Post to Twitter

Developing ASP.NET MVC 3 Application with EF CTP (Part 4)

In this post I will examine a couple of things.  I am going to use jQuery calendar UI functionality to improve user interface.  I will also add client side validation to my input form.

First, let’s add calendar control.  To do so, we have to download jQuery UI from .http://jqueryui.com/

Once this is completed, I will copy jquery.ui.core.js and jquery.ui.datepicker.js into Scripts folder of my application and include them in my project.  I will also copy calendar.gif as image for calendar button.  Next, I will add links to those scripts to my master page – in case of Razor view engine it is _Layout.cshtml.  Here is what it looks like:

<head>
    <title>@View.Title</title>
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery-1.4.1.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
    <link href="@Url.Content("~/Content/jquery-ui-1.8.6.custom.css")" rel="stylesheet" type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery.ui.core.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.ui.datepicker.js")" type="text/javascript"></script>
 
</head
>

 

It appears that if I just drag the script into _Layout.cshtml, then it does not work.  I had to add @Url.Content to make it work.  Now that this is completed, I have to update my partial page for blog entry and update my date textbox to use date picker from jQuery.  Here is what my code looks like now:

            <div class="editor-label">
                @Html.LabelFor(model => model.PostedOn)
           
</div>
            <div class="editor-field">
                @if
(Model.PostedOn.HasValue)
                {
                   
<input type="text" name="PostedOn" id="PostedOn" class="uidatepicker" 
value=@string.Format("{0:MM/dd/yyyy}", Model.PostedOn) />
                }
               
else
                { 
                   
<input type="text" name="PostedOn" id="PostedOn" class="ui-datepicker" />
                }
                @Html.ValidationMessageFor(model => model.PostedOn)
           
</div
>

 

As you can see, the code is pretty simple, but I will explain it in more detail just in case.  Since I am using formatting for the value, I would like to account for blank date.  If I do not do conditional control, my blank date will show up as “/”.  This is pretty ugly, so I am using different input controls – one with formatting, the other without.  Now, I need to call datepicker function  to setup my input control for Posted On date.  I am going to use ready function and add a small script to the bottom of my partial view I am using to edit blog:

<script type="text/javascript">
    $().ready(function
() {
        $(
‘.ui-datepicker’
).datepicker({
            dateFormat:
‘mm/dd/yy’
,
            buttonImage:
@Url.Content("~/Content/calendar.gif")
,
            buttonImageOnly:
true
,
            showOn:
"button"
        });
    });

</script
>

 

A few configuration options for date picker as pretty simple.  I am using month/day/year format, I am using the image I got from jQuery, and I showing image only, not the button and image on it.  That is all there is to it.  Now when I click on calendar image, I get calendar popup.

 

Next step is to get client validation to work.  I need a couple of scripts I am including in the code above: jquery, jquery.validate, jquery.validate.unobtrusive.  Next step is to simply enable validation on my view by calling EnableCleintValidation as in below (in bold):

@model MvcSampleApp.Models.BlogEntry
@{Html.EnableClientValidation();}
@
using
(Html.BeginForm())
{
@Html.ValidationSummary(
true
)
 
       
<fieldset
>

Here is the final version of my view:

@model MvcSampleApp.Models.BlogEntry
@{Html.EnableClientValidation();}
@
using (Html.BeginForm())
{
@Html.ValidationSummary(
true
)
 
       
<fieldset>
            <legend>Blog Post</legend>
            <div class="editor-label">
                @Html.LabelFor(model => model.Title)
           
</div>
            <div class="editor-field">
                @Html.TextBoxFor(model => model.Title) 
                @Html.ValidationMessageFor(model => model.Title)
           
</div>
            <div class="editor-label">
                @Html.LabelFor(model => model.Title)
           
</div>
            <div class="editor-field">
                @Html.DropDownListFor(model => model.CategoryID, new SelectList(Model.Categories, "CategoryId", "CategoryName", Model.CategoryID), "– Select Category –"
)
                @Html.ValidationMessageFor(model => model.CategoryID)
           
</div>
            <div class="editor-label">
                @Html.LabelFor(model => model.PostText)
           
</div>
            <div class="editor-field">
                @Html.TextAreaFor(model => model.PostText) 
                @Html.ValidationMessageFor(model => model.PostText)
           
</div>
            <div class="editor-label">
                @Html.LabelFor(model => model.PostedOn)
           
</div>
            <div class="editor-field">
                @if
(Model.PostedOn.HasValue)
                {
                   
<input type="text" name="PostedOn" id="PostedOn" class="ui-datepicker" value=@string.Format("{0:MM/dd/yyyy}", Model.PostedOn) />
                }
               
else
                { 
                   
<input type="text" name="PostedOn" id="PostedOn" class="ui-datepicker" />
                }
                @Html.ValidationMessageFor(model => model.PostedOn)
           
</div>
            <div>
                <input type="submit" value=@TempData["Action"] />
            </div>
            @Html.Hidden("BlogEntryId"
)
       
</fieldset>
 
}
 

<script type="text/javascript">
    $().ready(function
() {
        $(
‘.ui-datepicker’
).datepicker({
            dateFormat:
‘mm/dd/yy’
,
            buttonImage:
@Url.Content("~/Content/calendar.gif")
,
            buttonImageOnly:
true
,
            showOn:
"button"
        });
    });

</script
>

 

You can see that validation works by typing one letter into title and tabbing out. You will see immediate error without post back.  This is because I have a rule on my title:

        [Display(Name = "Title")]
        [
StringLength
(30, MinimumLength = 5)]
        [
Required
]
       
public string Title { get; set; }

 

image

And that is all there is to it.

Thanks.

Post to Twitter

Developing ASP.NET MVC 3 Application with EF CTP (Part 3)

Today I will concentrate on refactoring existing code and adding other links to my application, such as delete and edit links.

First things first, let’s do a bit of refactoring in advance of adding more views.  As I noticed, edit, delete and create views are the same with the exception of title for the submit button,  So, I am going to create a partial view that encompasses basic edit functionality along with submit button.  I am going to extract the title into a variable using TempData dictionary off the ViewResult object.  For example, here is how I am going to put “Delete” label into the view result:

view.TempData.Add("Action", "Delete");

 

I will use the same Action key in create and add methods as well.  Here is what code in my controller look like for the entire delete method:

        public ActionResult Delete(int id)
        {
           
BlogEntry entry = null
;
           
using (BlogContext context = new BlogContext
())
            {
                entry = context.Entries.Find(id);
                entry.CategoryID = entry.Category.CategoryId;
                entry.Categories = GetCaregories();
            }
           
var
view = View(entry);
            view.TempData.Add(
"Action", "Delete"
);
           
return view;
        }

 

Now I am going to refactor the view itself.  I am creating new view following the same routing as in part 2 of the post, but I will check Partial View checkbox.  Here is what my partial view (CreatePartial.cshtml) looks like:

@model MvcSampleApp.Models.BlogEntry
 
  @using (Html.BeginForm()) {
        @Html.ValidationSummary(true)
 
        <fieldset>
            <legend>Blog Post</legend>
            
            <div class="editor-label">
                @Html.LabelFor(model => model.Title)
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(model => model.Title)
                @Html.ValidationMessageFor(model => model.Title)
            </div>
 
                          <div class="editor-label">
                @Html.LabelFor(model => model.Title)
            </div>
            <div class="editor-field">
                @Html.DropDownListFor(model=>model.CategoryID, 
new SelectList(Model.Categories, "CategoryId", "CategoryName", Model.CategoryID), 
"– Select Category –")
                @Html.ValidationMessageFor(model => model.CategoryID)
            </div>
            
            <div class="editor-label">
                @Html.LabelFor(model => model.PostText)
            </div>
            <div class="editor-field">
                @Html.TextAreaFor(model => model.PostText)
                @Html.ValidationMessageFor(model => model.PostText)
            </div>
            
            <div class="editor-label">
                @Html.LabelFor(model => model.PostedOn)
            </div>
            <div class="editor-field">
                @Html.TextBox("PostedOn", string.Format("{0:MM/dd/yyyy}", Model.PostedOn))
                @Html.ValidationMessageFor(model => model.PostedOn)
            </div>
            <div>
                  <input type="submit" value=@TempData["Action"] />
             </div>
             @Html.Hidden("BlogEntryId")
        </fieldset>
 
    }

 

Now, our old Create view looks as follows:

@model MvcSampleApp.Models.BlogEntry
 
@{
    View.Title = "Create";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
 
<h2>Create</h2>
@{Html.RenderPartial("CreatePartial", Model);}
<div>
    @Html.ActionLink("Back to List", "Index")
</div>
 
 

 

Super simple.  Delete and Edit views look identical with exception of the title.  Very clean end result for all my refactoring efforts.  Here is the final code for my controller:

using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Web.Mvc;
using
MvcSampleApp.Models;
 

namespace
MvcSampleApp.Controllers
{
   
public class BlogsController : Controller
    {
       
//
        // GET: /Blogs/
 
       
public ActionResult
Index()
        {
           
using (BlogContext context = new BlogContext
())
            {
                context.Database.Connection.ConnectionString =
                   
ConfigurationManager.ConnectionStrings["BlogsConnectionString"
].ConnectionString;
               
var blogs = (from one in
context.Entries
                            
orderby one.PostedOn descending
                             select
one).ToList();
               
return
View(blogs);
            }
        }
 
       
//
        // GET: /Blogs/Create
 
 
       
public ActionResult
Create()
        {
           
IEnumerable<BlogCategory
> categories = GetCaregories();
           
var view = View(new BlogEntry
() { Categories = categories });
            view.TempData.Add(
"Action", "Create"
);
           
return
view;
        }
 
       
private static IEnumerable<BlogCategory
> GetCaregories()
        {
           
IEnumerable<BlogCategory
> categories;
           
using (BlogContext context = new BlogContext
())
            {
                categories = (
from one in
context.Categories
                             
orderby
one.CategoryName
                             
select
one).ToList();
            }
           
return
categories;
        }
 
       
private BlogCategory GetCategory(int
categoryID)
        {
           
using (BlogContext context = new BlogContext
())
            {
               
return
context.Categories.Find(categoryID);
            }
        }
 
       
//
        // POST: /Blogs/Create
 
        [
HttpPost
]
       
public ActionResult Create(BlogEntry
entry)
        {
 
           
try
            {
               
if
(entry.CategoryID > 0)
                {
                    entry.Category = GetCategory(entry.CategoryID);
                }
               
if
(TryValidateModel(entry))
                {
                   
using (BlogContext context = new BlogContext
())
                    {
                        context.Entries.Add(entry);
                        context.SetAsUnchanged(entry.Category);
                        context.SaveChanges();
                    }
 
                   
return RedirectToAction("Index"
);
                }
               
else
                {
                    entry.Categories = GetCaregories();
                   
return
View(entry);
                }
            }
           
catch
            {
               
return
View();
 
            }
        }
 
       
//
        // GET: /Blogs/Edit/5
 
       
public ActionResult Edit(int
id)
        {
           
BlogEntry entry = null
;
           
using (BlogContext context = new BlogContext
())
            {
                entry = context.Entries.Find(id);
                entry.CategoryID = entry.Category.CategoryId;
                entry.Categories = GetCaregories();
            }
           
var
view = View(entry);
            view.TempData.Add(
"Action", "Update"
);
           
return
view;
        }
 
       
//
        // POST: /Blogs/Edit/5
 
        [
HttpPost
]
       
public ActionResult Edit(int id, BlogEntry
entry)
        {
           
try
            {
               
if
(entry.CategoryID > 0)
                {
                    entry.Category = GetCategory(entry.CategoryID);
                }
               
if
(TryValidateModel(entry))
                {
                    entry.BlogEntryId = id;
                   
using (BlogContext context = new BlogContext
())
                    {
                        context.Entries.Attach(entry);
                        context.SetAsModified(entry);
                        context.SaveChanges();
                    }
 
                   
return RedirectToAction("Index"
);
                }
               
else
                {
                    entry.Categories = GetCaregories();
                   
return
View(entry);
                }
            }
           
catch
            {
               
return
View();
 
            }
        }
 
       
//
        // GET: /Blogs/Delete/5
 
       
public ActionResult Delete(int
id)
        {
           
BlogEntry entry = null
;
           
using (BlogContext context = new BlogContext
())
            {
                entry = context.Entries.Find(id);
                entry.CategoryID = entry.Category.CategoryId;
                entry.Categories = GetCaregories();
            }
           
var
view = View(entry);
            view.TempData.Add(
"Action", "Delete"
);
           
return
view;
        }
 
       
//
        // POST: /Blogs/Delete/5
 
        [
HttpPost
]
       
public ActionResult Delete(int id, BlogEntry
entry)
        {
          
try
            {
               
if
(entry.CategoryID > 0)
                {
                    entry.Category = GetCategory(entry.CategoryID);
                }
               
if
(TryValidateModel(entry))
                {
                    entry.BlogEntryId = id;
                   
using (BlogContext context = new BlogContext
())
                    {
                        context.Entries.Attach(entry);
                        context.Entries.Remove(entry);
                        context.SaveChanges();
                    }
 
                   
return RedirectToAction("Index"
);
                }
               
else
                {
                    entry.Categories = GetCaregories();
                   
return
View(entry);
                }
            }
           
catch
            {
               
return View();
 
            }
        }
    }
}

 

A couple more things to notice.  By default foreign keys are created with Cascade Deletes option.  This is not appropriate behavior for my use case.  I am changing this behavior in OnModelCreating method of my context.  Here is the final version of my context class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;
using System.Configuration;
using
System.Data.Entity.ModelConfiguration;
 

namespace
MvcSampleApp.Models
{
   
public class BlogContext : DbContext
    {
       
public
BlogContext()
        {
           
this
.Database.Connection.ConnectionString =
                   
ConfigurationManager.ConnectionStrings["BlogsConnectionString"
]
                    .ConnectionString;
        }
       
public DbSet<BlogCategory> Categories { get; set
; }
       
public DbSet<BlogEntry> Entries { get; set
; }
 
       
protected override void OnModelCreating(System.Data.Entity.ModelConfiguration.ModelBuilder
modelBuilder)
        {
           
base
.OnModelCreating(modelBuilder);
 
            modelBuilder.Entity<
BlogEntry
>().HasKey(a => a.BlogEntryId);
            modelBuilder.Entity<
BlogCategory
>().HasKey(a => a.CategoryId);
            modelBuilder.Entity<
BlogEntry>().HasRequired(e => e.Category).WithMany().WillCascadeOnDelete(false
);
        }
 
       
public void SetAsModified(object
entry)
        {
           
this.ObjectContext.ObjectStateManager.ChangeObjectState(entry, System.Data.EntityState
.Modified);
        }
 
       
public void SetAsUnchanged(object
entry)
        {
           
this.ObjectContext.ObjectStateManager.ChangeObjectState(entry, System.Data.EntityState.Unchanged);
        }
    }
}

 

I am using helper methods to SetAs… to ensure that I am not creating duplicate categories.  You can see how I am using these helper methods above in controller class.

You can download entire solution here.

Post to Twitter

Developing ASP.NET MVC 3 Application with EF CTP (Part 2)

First thing we want to do is create a controller for blog entries.  To do so, we will right-click on Controllers folder, select Add, then Controller.

image

On next screen we give it a name (BlogsController) and check the checkbox to create CRUD operations:

image

First method we are going to fill is Index method that will return the list of blog entries.  We will not use EF to return the list of blog posts sorted in ascending order by date.  We are not going to implement paging for now, we will come back to do this later.  Here is completed Index method(Index is just a naming convention)

        public ActionResult Index()
        {
           
using (BlogContext context = new BlogContext
())
            {
                context.Database.Connection.ConnectionString = 
                   
ConfigurationManager.ConnectionStrings["BlogsConnectionString"
].ConnectionString;
               
var blogs = (from one in
context.Entries
                            
orderby one.PostedOn descending
                             select
one).ToList();
               
return View(blogs);
            }
        }

 

As you can see the code is pretty simple.  Next step is to create index view. To do this right-click in the body of the method above and select Add View

image

Below you can see the options I selected.  We create strongly typed view based on BlogEntry class.  We use Razor (new in MVC 3.) engine and select list as view type.  Once we click Add, the IDE will scaffold the object and build the HTML view for us – Index.cshtml.  This new view will be added to Blogs folder.  Again we are using naming conventions to match controller and view

 

image

We are going to clean up the view by removing ID and text columns from the table.  We also update links to use appropriate ID from the object.  Here is final version of our view:

 

@model IEnumerable<MvcSampleApp.Models.BlogEntry>
 
@{
    View.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
 
    <h2>Index</h2>
 
    <p>
        @Html.ActionLink("Create New", "Create")
    </p>
 
    <table>
        <tr>
            <th></th>
            <th>
                Title
            </th>
            <th>
                PostedOn
            </th>
        </tr>
 
    @foreach (var item in Model) {
    
        <tr>
            <td>
                @Html.ActionLink("Edit", "Edit", new { id=item.BlogEntryId }) |
                @Html.ActionLink("Details", "Details", new { id=item.BlogEntryId }) |
                @Html.ActionLink("Delete", "Delete", new { id=item.BlogEntryId })
            </td>
            <td>
                @item.Title
            </td>
            <td>
                @String.Format("{0:g}", item.PostedOn)
            </td>
        </tr>
    
    }
 
    </table>
 
 

 

To make this work, I had to update by Blog Entry class.  I had to add category ID in order to bind to it in the UI.  Question now is: looks like I need model objects on top of EF classes.  This seems counter-productive to me as I would have to duplicate properties.  I think the goal would be to use composition or inheritance to have model derive or expose EF class.  I will work on refactoring efforts right after the app is working.

    public class BlogEntry
    {
        [
Key
]
       
public int BlogEntryId { get; private set
; }
 
        [
Display(Name = "Title"
)]
        [
StringLength
(30, MinimumLength = 5)]
        [
Required
]
       
public string Title { get; set
; }
 
        [
Display(Name = "Post Text"
)]
        [
StringLength(int
.MaxValue)]
        [
Required
]
       
public string PostText { get; set
; }
 
        [
Display(Name = "Category"
)]
       
public virtual BlogCategory Category { get; set
; }
 
        [
Display(Name = "Post Date"
)]
        [
Range(typeof(DateTime), "1/1/1900", "12/31/2099"
)]
        [
Required
]
       
public DateTime? PostedOn { get; set
; }
 
       
public IEnumerable<BlogCategory> Categories { get; set
; }
 
        [
Required
]
        [
Display(Name = "Category"
)]
       
public int CategoryID { get; set; }
    }

 

In Razor syntax @ symbol indicates C# code, where < symbol indicates HTML tags.  As you can see on top we define model for the view, which in our case is the argument passed into the View in the Index method of the controller.  We also need to add a link to the menu for blog posts.  We add it to the _Layout.cshtml view:


                <ul id="menu">
                    <li>@Html.ActionLink("Home", "Index", "Home")</li>
                    <li>@Html.ActionLink("About", "About", "Home")</li>
                    <li>@Html.ActionLink("Blogs", "Index", "Blogs")</li>
                </ul>

 

Next step is to create new post view.  We also need to add code to Create method of the new view.  Here is how Create method looks:

        public ActionResult Create()
        {
           
return View(new BlogEntry());
        }

 

Now, same step as above – right-click, add view, select Create option from View Content drop down.  Then I will remove ID field.  Here is the end result of that.

@model MvcSampleApp.Models.BlogEntry
 
@{
    View.Title = "Create";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
 
<h2>Create</h2>
 
    @using (Html.BeginForm()) {
        @Html.ValidationSummary(true)
 
        <fieldset>
            <legend>Blog Post</legend>
            
            <div class="editor-label">
                @Html.LabelFor(model => model.Title)
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(model => model.Title)
                @Html.ValidationMessageFor(model => model.Title)
            </div>
 
                          <div class="editor-label">
                @Html.LabelFor(model => model.Title)
            </div>
            <div class="editor-field">
                @Html.DropDownListFor(model=>model.CategoryID, new SelectList(Model.Categories, "CategoryId", "CategoryName", Model.CategoryID), "– Select Category –")
                @Html.ValidationMessageFor(model => model.Title)
            </div>
            
            <div class="editor-label">
                @Html.LabelFor(model => model.PostText)
            </div>
            <div class="editor-field">
                @Html.TextAreaFor(model => model.PostText)
                @Html.ValidationMessageFor(model => model.PostText)
            </div>
            
            <div class="editor-label">
                @Html.LabelFor(model => model.PostedOn)
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(model => model.PostedOn)
                @Html.ValidationMessageFor(model => model.PostedOn)
            </div>
            <div>
                                   <input type="submit" value="Create" />
                          </div>
        </fieldset>
 
    }
 
    <div>
        @Html.ActionLink("Back to List", "Index")
    </div>
 
 

Next step is to create controller method to save new blog post

        [HttpPost]
       
public ActionResult Create(BlogEntry
entry)
        {
 
           
try
            {
               
if
(entry.CategoryID > 0)
                {
                    entry.Category = GetCategory(entry.CategoryID);
                }
               
if
(TryValidateModel(entry))
                {
                   
using (BlogContext context = new BlogContext
())
                    {
                        context.Database.Connection.ConnectionString =
                   
ConfigurationManager.ConnectionStrings["BlogsConnectionString"
]
                    .ConnectionString;
                        context.Entries.Add(entry);
                        context.SaveChanges();
                    }
 
                   
return RedirectToAction("Index"
);
                }
               
else
                {
                    entry.Categories = GetCaregories();
                   
return
View(entry);
                }
            }
           
catch
            {
               
return View();
 
            }
        }

 

There are still parts of the method that can be optimized.  I will look at those once the application is completed.

In the next post I will look at the edit and delete methods.

Post to Twitter

Developing ASP.NET MVC 3 Application with EF CTP (Part 1)

I this post I will walk through steps of creating an ASP.NET MVC 3 application using new code first entity framework CTP as data access and business layer.  Just a few upfront comments.  Both technologies are in preview state right now, but will likely be released in first half of next year.

To get started we have to download and install them.  To make this simpler, I will use NuGet (formerly  NuPack) which is package management software for .NET applications.  You can find it here.  Visual Studio 2010 is required to follow along with the demo, by the way.  You can download ASP.NET MVC 3.0 beta here.

Now that it has been downloaded and installed, let’s create new project.

image

Next step to pick the view engine you want to use.  You can select either ASPX (ASP.NET) or new Razor engine that will ship with MVC 3.0 and new product – Web Matrix.

image

We will go ahead and also select to create Unit Test project.

What the wizard builds for us is empty site with home view and registration service that uses membership provider.  Let’s run the app to see if everything worked correctly.  We can open web.config and verify that the system is using ASP.NET SQL Membership provider for login:

<configuration>
  <
connectionStrings
>
    <
add name=ApplicationServices

         connectionString=data source=.\SQLEXPRESS;Integrated Security=SSPI;
AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true

         providerName=System.Data.SqlClient
/>
  </
connectionStrings>
 
  <appSettings
>
    <
add key=enableSimpleMembership value=false
/>
    <
add key=ClientValidationEnabled value=false
/>
    <
add key=UnobtrusiveJavaScriptEnabled value=true
/>
  </
appSettings>
 
  <system.web
>
 
    <authentication mode=Forms
>
      <
forms loginUrl=~/Account/LogOn timeout=2880
/>
    </
authentication>
 
    <membership
>
      <
providers
>
        <
clear
/>
        <
add name=AspNetSqlMembershipProvider
 
            
type=System.Web.Security.SqlMembershipProvider
 
            
connectionStringName=ApplicationServices
             enablePasswordRetrieval=false
 
            
enablePasswordReset=true
 
            
requiresQuestionAndAnswer=false
 
            
requiresUniqueEmail=false
             maxInvalidPasswordAttempts=5
 
            
minRequiredPasswordLength=6
             minRequiredNonalphanumericCharacters=0
 
            
passwordAttemptWindow=10
             applicationName=/
/>
      </
providers
>
    </
membership
>

Now, let’s add our code.  Since I absolutely lack any imagination, I will create blogging application.  Each blog will contain title, text, posted date and category.  Let’s create entities for blogs and categories using EF code first CTP.  First, let’s install CTP 4 for entity framework.  To do, we will use NuGet functionality.  Right click on references node in solution and select add package, search for EF and Select EFCTP 4:

image

 

image

Now, let’s create our two classes – categories and blog posts.  We will add them to the Model folder. Blog category class is very simple:

    public class BlogCategory
    {
        [
Key
]
       
public int CategoryId { get; private set
; }
 
        [
Display(Name = "Category Name"
)]
       
public string CategoryName { get; internal set; }
 
    }

 

I made blog entries property virtual to enable lazy loading.  Blog entry class is only slightly mode complicated:

    public class BlogEntry
    {
        [
Key
]
       
public int BlogEntryId { get; private set
; }
 
        [
Display(Name = "Title"
)]
        [
StringLength
(30, MinimumLength = 5)]
        [
Required
]
       
public string Title { get; set
; }
 
        [
Display(Name = "Post Text"
)]
        [
StringLength
(30, MinimumLength = 5)]
        [
Required
]
       
public string PostText { get; set
; }
 
        [
Display(Name = "Category"
)]
       
public BlogCategory Category { get; set
; }
 
        [
Display(Name = "Post Date"
)]
        [
Range(typeof(DateTime), "1/1/1900", "12/31/2099"
)]
       
public DateTime? PostedOn { get; set; }
    }

 

As you can see, I am using attributes from DataAnnotations namespace to describe the properties of my classes.  Next class I need is DbContext, which essentially is my database abstraction:

    public class BlogContext : DbContext
    {
       
public DbSet<BlogCategory> Categories { get; set
; }
       
public DbSet<BlogEntry> Entries { get; set
; }
 
       
protected override void OnModelCreating(

          System.Data.Entity.ModelConfiguration.ModelBuilder modelBuilder)
        {
           
base
.OnModelCreating(modelBuilder);
 
            modelBuilder.Entity<
BlogEntry
>().HasKey(a => a.BlogEntryId);
            modelBuilder.Entity<
BlogCategory>().HasKey(a => a.CategoryId);
 
        }
    }

 

 

As you can see I have two properties – for blog entries and categories.  I also modify default configuration of my database by overriding OnModelCreating and specifying my primary key columns and table names.  One more class I would like to add to customize database creation behavior that is very useful for development:

    public class BlogDatabase :

       System.Data.Entity.Infrastructure.RecreateDatabaseIfModelChanges<BlogContext>
    {
       
protected override void Seed(BlogContext
context)
        {
            context.Categories.Add(
new BlogCategory()

             { CategoryName = “General” });
            context.Categories.Add(
new BlogCategory()

             { CategoryName = “Entity Framework” });
            context.Categories.Add(
new BlogCategory()

             { CategoryName = “Silverlight” });
        }
    }

 

This class inherits for recreate database behavior.  I am overriding Seed method to prepopulate my database with a handful of categories.  Now, I have to register my class in global.asax.  I am doing so by setting initializer in static method on database class.

        protected void Application_Start()
        {
           
AreaRegistration
.RegisterAllAreas();
           
Database.SetInitializer<BlogContext>(new BlogDatabase
());
 
            RegisterGlobalFilters(
GlobalFilters
.Filters);
            RegisterRoutes(
RouteTable.Routes);
        }

In the next post I will add some web pages to use these classes. 

Post to Twitter

Silverlight vs. HTML 5

It is time for me to jump on bandwagon of discussing the latest comments out of Microsoft regarding Silverlight.  If you have not read the latest commend by Bob Muglia, Microsoft VP, you can read his interview with Mary-Jo Foley here.  One particular paragraph bothers me a ton:

Silverlight is our development platform for Windows Phone,” he said. Silverlight also has some “sweet spots” in media and line-of-business applications, he said.

 

I am seriously bugged by this maybe unintentional dismissal of Silverlight as development platform for web applications.  I have been holding the following opinion on the subject for quite some time.  I think for public facing web sites Silverlight maybe not be an ideal fit since it increases the barrier of entry for consumers.  However, for internal business applications and B2B applications it is a great fit.  This is primary because you have pretty good control in business environment and you can very easily ensure that all computers have Silverlight installed.  Thus, Silverlight plugin simply becomes a prerequisite for such applications.  I have been developing B2B applications in Silverlight for over 2 years, and have not seen any problems with this approach until Bob Muglia’s comment.  Based on my personal experience, you can delivery better applications faster in Silverlight vs. traditional web technologies such as APS.NET.  Granted, you have a learning curve to overcome, but isn’t this the case with any technology?  If one is in software business, studying becomes an essential part of one’s carrier. 

Let’s take the following hypothetical situation. You are a software company that developed a Silverlight B2B application over the course of a couple of years.  You are successfully selling it.  All of a sudden your competitor with an inferior product, which is developed using ASP.NET reads the comment above.   They immediately incorporate this fact into their marketing approach, costing your sales.  You can see how a relatively small comment can cause a company that spent millions in development costs a multimillion dollar sale.

I do not think Silverlight is going away by any stretch of imagination.  It is and will remain a great platform for web based business applications.  However, it would be more than necessary for Microsoft to clear the air and do so with a sense of urgency.  I do not believe that dismissive attitude toward Silverlight is correct, and probably was an unintended consequence of stressing the importance of HTML 5 for Microsoft.

Post to Twitter

Presentation at Atlanta MS Pros

Yesterday I did a presentation at local Atlanta MS Pros users group on LightSwitch.  I just want to post the slides for the presentation.  These slides also contain a bunch of links to LightSwitch resources.

You can download the presentation here.

Post to Twitter

Using Entity Framework 4.0 CTP

In this post I will take a look at the new features in the next release of entity framework.

Primary feature set is centered around what is commonly referred to as “Code First” approach to Entity Framework.  With code first approach you write the code first, then entity framework runtime dynamically figures out how to persist your classes to database.

So, you start with plain ol’ LCR classes (POCO classes).  For my small example I will have list of companies with their contacts.  Here is what my classes look like:

        public Company()
        {
            Contacts = new ObservableCollection<CompanyContact>();
            Contacts.CollectionChanged += (o, e) =>
                {
                    if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
                    {
                        foreach (var item in e.NewItems)
                        {
                            (item as CompanyContact).ParentCompany = this;
                        }
                    }
                };
        }
        public int CompanyId { get; set; }
        public string CompanyName { get; set; }
        public DateTime DateAdded { get; set; }
        public virtual ObservableCollection<CompanyContact> Contacts { get; private set; }
    }
 
    public class CompanyContact
    {
        public int CompanyContactId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public Company ParentCompany { get; set; }
    }

 

Now we need to take a look at key classes that enable POCO persistence in Entity Framework CTP : DbSet and DbContext.

DbSet is a set of POCO classes that is pretty much a simplified version of ObjectSet.  It gives developers ability to add and remove items to.  DbContext is really at heart of CTP version, and it is a simplified version of ObjectContext.  It may contain any number of properties that are of type DbSet<T> where T is any POCO class.

Here is what this class looks like for my Rolodex mini-application:

    public class CompanyContext : DbContext
    {
        public CompanyContext()
            : base()
        {
        }
        public DbSet<Company> Companies { get; set; }
 
        public DbSet<CompanyContact> Contacts { get; set; }

 

That is all we need to do at a high level, dealing with out POCO classes.  Now, the key part – let’s define our rules and persistence details.  There is a number of ways this can be done, I am picking virtual method OnModelCreating on DbContext that allows me to configure rules and persistence details.  Here is what I am doing for my couple of classes:

        protected override void OnModelCreating(System.Data.Entity.ModelConfiguration.ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
 
            // configure primary key
            modelBuilder.Entity<Company>()
                .HasKey(c => c.CompanyId);
 
            // company id is identity
            modelBuilder.Entity<Company>().Property(c => c.CompanyId)
                .StoreGeneratedPattern = System.Data.Metadata.Edm.StoreGeneratedPattern.Identity;
 
            //maximum length for company name
            modelBuilder.Entity<Company>()
               .Property(c => c.CompanyName).MaxLength = 40;
 
            //name required
            modelBuilder.Entity<Company>()
                .Property(c => c.CompanyName).Optional = false;
 
            // One to many relationship
            modelBuilder.Entity<Company>()
                .HasMany(c => c.Contacts);
 
            //contact id is identity
            modelBuilder.Entity<CompanyContact>().Property(c => c.CompanyContactId)
                .StoreGeneratedPattern = System.Data.Metadata.Edm.StoreGeneratedPattern.Identity;
 
            // primary key for contacts
            // company cannot be null
            modelBuilder.Entity<CompanyContact>()
                .HasKey(c => c.CompanyContactId)
                .HasRequired(c => c.ParentCompany);
 
            //last name required
            modelBuilder.Entity<CompanyContact>()
                .Property(c => c.LastName).Optional = false;
 
            //maximum length for last name
            modelBuilder.Entity<CompanyContact>()
                .Property(c => c.LastName).MaxLength = 50;
 
            //first name required
            modelBuilder.Entity<CompanyContact>()
               .Property(c => c.FirstName).Optional = false;
 
            //maximum length for first name
            modelBuilder.Entity<CompanyContact>()
              .Property(c => c.FirstName).MaxLength = 30;
 
 
        }

 

As you can see from my comments I am configuring nullable / non nullable properties via Optional properties off Property method.  I am also configuring Identity properties via StoreGeneratedPattern.  I am also configuring maximum length for my fields at the same time.

The next step is to create a database and add data.  Creating database is super easy with DbContext:

            using (var context = new CompanyContext())
            {
                context.Database.Connection.ConnectionString = @"Server=(local);Database=RolodexEFCtp;Trusted_Connection=True;";
                context.Database.CreateIfNotExists();

 

That is all that takes.  At the time my context is created, OnModelCreating will fire, thus configuring all my persistence options.  Now, let’s populate DB with data:

                var company = new Company()
                    {
                        CompanyName = "Mine",
                        DateAdded = DateTime.Now
                    };
                context.Companies.Add(company);
 
                company.Contacts.Add(new CompanyContact()
                {
                    FirstName = "Sergey",
                    LastName = "Basrskiy"
                });
 
                company.Contacts.Add(new CompanyContact()
                {
                    FirstName = "John",
                    LastName = "Doe"
                });
 
                company = new Company()
                {
                    CompanyName = "Yours",
                    DateAdded = DateTime.Now
                };
                context.Companies.Add(company);
 
                company.Contacts.Add(new CompanyContact()
                {
                    FirstName = "Jane",
                    LastName = "Doe"
                });
 
                company.Contacts.Add(new CompanyContact()
                {
                    FirstName = "John",
                    LastName = "James"
                });
                context.SaveChanges();

 

As before, the last line of dealing with saving is calling SaveChanges() method. 

Now, let’s take a look at how to get the data back from database:

            using (var context = new CompanyContext())
            {
                context.Database.Connection.ConnectionString = @"Server=(local);Database=RolodexEFCtp;Trusted_Connection=True;";
                var companies = context.Set<Company>().Include("Contacts").OrderBy(c => c.CompanyName).ToList();
            }

 

The last line will get me the list of companies, each populated with the list of corresponding contacts.  At this point I am doing everything that Entity Framework is designed for – get me the data from database and save data to database, except now I am configuring everything in code and creating storage on the fly.  Most importantly, I use POCO classes instead of Entity classes.

Now we just have to wait and see when new version of Entity Framework is released.

You can download CTP here: http://www.microsoft.com/downloads/en/details.aspx?FamilyID=4e094902-aeff-4ee2-a12d-5881d4b0dd3e&displaylang=en

You can find more details on CTP on entity framework team blog: http://blogs.msdn.com/b/adonet/archive/2010/07/14/ctp4codefirstwalkthrough.aspx

Thanks

Post to Twitter

Back to Windows Phone 7 Database

Since Microsoft now released RTM version of their tools for Windows Phone 7 development, I updated my phone database project to the latest version as well.  You can find this project here : http://winphone7db.codeplex.com/.

I added also a new feature – ability to create tables with data on desktop, then load them into the database when application runs for the first time.  In order to optimize the process, I am setting this table content (XML files) as Content in my sample application.  If you set your additional files as resources, they will be immediately loaded into memory, while this is not the same for files marked as content.  Here is a screenshot that illustrates the settings.

image

Next step is to read content in Windows phone 7 application.  Here is how I am doing it:

string

content = string.Empty;
Uri uri = new Uri(“test.xml”, UriKind.Relative);
StreamResourceInfo info = Application.GetResourceStream(uri);
using (StreamReader reader = new StreamReader(info.Stream))
{
    content = reader.ReadToEnd();
}

 

 

Pretty easy, hah?

Please look at downloaded application at http://winphone7db.codeplex.com/. for sample use of my database.

Thanks.

Post to Twitter

Using WinDbg to Find Memory Leaks in Silverlight Applications

In light of recent issues with memory leaks in Silverlight and the fact that service pack that was supposed to address these issues was released last week, I found myself working on an application, trying to confirm that it does not leak any longer.  To simplify my approach, I created a destructor for my view with the following code:

        ~BaseView()
        {
#if DEBUG
            System.Diagnostics.Debug.WriteLine("Destructed view " + this.GetType().Name);
#endif
        }

 

This code will echo to Debug window when garbage collector hits my view.  To my dismay, the view was never collected after being removed from a region.  (I am using Prism for my sample application).  I did some research, and decided to use WinDbg to help me pinpoint memory leaks.

First step is to download tools for my Windows 7 64 bit machine.  I found the link here:http://www.microsoft.com/whdc/devtools/debugging/install64bit.mspx

So I installed checking all options.  I started WinDbg and tried to load Silverlight debug symbols from (C:\\Program Files (x86)\\Microsoft Silverlight\\4.0.50826.0\\sos.dll).  Unfortunately I got an error – not a valid 32 bit application, even though I am running 64 bit.  Come to find out, I actually need 32 bit version of WinDbg since Silverlight only runs in 32 bit environment.  Would be nice to have a better message, but here we go.  Next step is to install 32 bit version of WinDbg.  make sure you checked ALL options during main tools install.  If so, you will find that version here: C:\Program Files\Microsoft SDKs\Windows\v7.1\Redist\Debugging Tools for Windows.

Now, start WinDbg from Program Files (x86) folder.  I just use search feature in Windows 7, and type WinDbg into search box after clicking on Start button.

Now I run my application in IE, and load my UserView (user control) a few times, and close it (remove from region) a few times, 3 times to be specific..

With WinDbg running, I now have to attach to a process, Internet explorer in my case. Make sure you do not have Visual Studio running in debug mode, or you will get  an error trying to attach second debugger to IE.  I use File->Attach To Process menu in WinDbg and look for iexplore process.  Then I will see Command window.  In the bottom portion of the window I see a textbox – this is WinDbg command line.  I type the following: .load C:\\Program Files (x86)\\Microsoft Silverlight\\4.0.50826.0\\sos.dll and hit enter.  Make sure to start with a period(.).

Now, let’s take a memory snapshot.  Type the following and hit enter: !dumpheap –stat 

Once that is done, hit Ctrl+Home to go to the top of command window, then hit Ctrl+F to pull up search window, type your control name (UserView) in my case and hit Enter.  You now will see how many instance of your view there are in memory:

05dcaa14        3          300 KSS.Silverlight.SystemWide.Views.UserView

In my case there are three.The first column is MT, which will contain my type.  using this value I can find addresses of each of three instances.  Type the following and hit Enter:

!dumpheap -MT 05dcaa14

Now I see addresses for each of three instances.  I pick up one at random to see the references that keep the object from being picked up by garbage collector.  Type the following and hit Enter:

!gcroot 12753bfc

Here is the output for this command:

0:035> !gcroot 12753bfc
Note: Roots found on stacks may be false positives. Run "!help gcroot" for
more info.
Scan Thread 4 OSTHread 1c28
Scan Thread 30 OSTHread cc4
Scan Thread 31 OSTHread 15b0
Scan Thread 33 OSTHread cb8
DOMAIN(05FE3BD8):HANDLE(Pinned):2f812f8:Root:  13594260(System.Object[])->
  125a8888(System.Collections.Generic.Dictionary`2[[System.IntPtr, mscorlib],[System.Object, mscorlib]])->
  127a9408(System.Collections.Generic.Dictionary`2+Entry[[System.IntPtr, mscorlib],[System.Object, mscorlib]][])->
  127dd420(System.Windows.Controls.Grid)->
  127dd484(System.Collections.Generic.Dictionary`2[[MS.Internal.IManagedPeerBase, System.Windows],[System.Object, mscorlib]])->
  127dd4d0(System.Collections.Generic.Dictionary`2+Entry[[MS.Internal.IManagedPeerBase, System.Windows],[System.Object, mscorlib]][])->
  127dd54c(System.Windows.Controls.Border)->
  127e9874(System.Collections.Generic.Dictionary`2[[MS.Internal.IManagedPeerBase, System.Windows],[System.Object, mscorlib]])->
  127e98c0(System.Collections.Generic.Dictionary`2+Entry[[MS.Internal.IManagedPeerBase, System.Windows],[System.Object, mscorlib]][])->
  127ddd88(System.Windows.Controls.Grid)->
  127dddec(System.Collections.Generic.Dictionary`2[[MS.Internal.IManagedPeerBase, System.Windows],[System.Object, mscorlib]])->
  127dde38(System.Collections.Generic.Dictionary`2+Entry[[MS.Internal.IManagedPeerBase, System.Windows],[System.Object, mscorlib]][])->
  127dde84(System.Windows.Controls.ScrollViewer)->
  127e97f0(System.Windows.Controls.ItemsPresenter)->
  127e9858(MS.Internal.CoreTypeEventHelper)->
  127ea1b4(System.Collections.Generic.Dictionary`2[[System.Int32, mscorlib],[MS.Internal.CoreTypeEventHelper+EventAndDelegate, System.Windows]])->
  127ea200(System.Collections.Generic.Dictionary`2+Entry[[System.Int32, mscorlib],[MS.Internal.CoreTypeEventHelper+EventAndDelegate, System.Windows]][])->
  127ea1a4(MS.Internal.CoreTypeEventHelper+EventAndDelegate)->
  127ea16c(System.Windows.Input.KeyEventHandler)->
  12760854(Telerik.Windows.Controls.RadComboBox)->
  12757a7c(System.Windows.Controls.Grid)->
  127cf2ac(System.Windows.Controls.ContentPresenter)->
  127cf188(System.Windows.Controls.Grid)->
  12757160(Groupbox.GroupBox)->
  12756df4(System.Windows.Controls.Grid)->
  12753bfc(KSS.Silverlight.SystemWide.Views.UserView)

You should start looking from the bottom and work your way up to the gcroot – garbage collector root object.  In my case I find RadComboBox object – first reference that looks like it is causing issues.  I remove the combo box from my UserView user control and repeat the test.  This time view disposes.  I found my leak!

More typically, leaks are caused by hanging references to your objects, most commonly by event handlers.  In my case this was not the case, but this is typically where you would look first.

Thanks.

Post to Twitter

Modular Silverlight Development, App.xaml, Blend and Resources

As I was working on one of my personal learning projects, I encountered a small problem. The project was Prism based with multiple modules.  I wanted to isolate my resource files, so I created a separate project that included my XAML resources, such as styles.  This approach works just fine by using merged dictionaries in App.xaml:

<Application 
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
   x:Class="MyApp.Silverlight.App"
            >
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/MyResources.Silverlight.Common;component/Resources/MyResourcesDictionary.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

 

Now I can reference those resource in my other modules’ screens and use them.  Now back to the original issue.  I can use styles from MyResourceDictionary.xaml, but Blend generates an error for me – it cannot find my resources.  Here is an easy way to overcome this issue.  You have to add the same dictionary into the resources of each screen:  In the example below I am showing resources area for a user control called MySampleView from MyApp module.,

    <MyApp:MySampleView.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="/MyResources.Silverlight.Common;component/Resources/MyResourcesDictionary.xaml"/>
            </ResourceDictionary.MergedDictionaries>
            <resource:Resource x:Key="LocalizedResource"/>
        </ResourceDictionary>
    </MyApp:MySampleView.Resources>

As you can see, I combine the styles dictionary with a local resource, in example localized user strings.  You can just as easily add converters, etc… in the same fashion.

There is some cost of course associated with merging dictionaries into each screen, but using Blend is a big benefit.  You can get around this issue by keeping this code commented out, and uncomment when using Blend

There is also another solution, involving having #DEBUG that moves this exact code into code behind of each view.  Of course, this is annoying as well, and this is when the base class for the view comes in.  Here is the code I could add to it to accomplish the same as XAML approach:

#if DEBUG
            var dictionary = new ResourceDictionary() 
                { Source = new Uri("/MyResources.Silverlight.Common;component/Resources/MyResourceDictionary.xaml", UriKind.RelativeOrAbsolute) };
            Resources.MergedDictionaries.Add(dictionary);
#endif

 

This of course underscores the usefulness of having base classes for all your major components, such as views in your applications.  It could be an inconvenience since you cannot just add new user control.  You would have to edit both XAML and code behind to change the inheritance structure of your user controls (views).

<MyApp:MySampleViewBase
   x:Class="MyApp.Views.MySampleView"

public partial class MySampleView : MySampleViewBase, IMySampleView

 

You can further optimize this process by creating custom control templates that would write all this code for you.  This way you would not have to modify the files after creating a new user control.

Thanks.

Post to Twitter

Encryption in Silverlight and .NET Applications

Today I would like to cover a specific use case that came up a few times in Silverlight applications I wrote.  For example, I wand a user to enter some sensitive information, encrypt it in Silverlight client, transfer it over to the server, then decrypt it and perforation some operations on that data.

First step of course is to find sufficiently strong encryption protocol that can be implemented in both Silverlight and .NET and be completely compatible between both run times.  I am going to go for AES encryption.  AES stands for “Advanced Encryption Standard”.  This standard is widely used and approved by US government and standard bodies.  See this article for details.

Luckily, AES encryption is implemented in both Silverlight and .NET run times, using exact same set of classes, primary one being AesManaged class.  My goal is to create a class that I can cross-compile in both runt times, so this comes in super handy.  Second, I wand to implement two methods Decrypt and Encrypt, while paying attention to IDisposable interfaces that the vast majority of classes inside Cryptography namespace implement.  Both static methods take two parameters, input string and a password to be used.  Of course, you have to make sure you use the same password in both methods while encrypting and decrypting information.  You should probably dynamically generate a password during handshake process between a Silverlight client and a .NET server.  I will also use maximum key size and block size of encryption.  I will also dynamically generate key (Key) and initialization vector(IV) properties.    I am going to now spare everyone a number of boring details, and will simply post final version of my utility class:  You can include this class in both .NET and Silverlight project, and even link the physical .cs file from one to the other to ensure that you only have a single version in source control.

Thanks

using System;
using System.Text;
using System.Security.Cryptography;
using System.IO;
 
namespace Encryption
{
    public static class EncryptionUtility
    {
 
        /// <summary>
        /// Encrypt the data
        /// </summary>
        /// <param name="input">String to encrypt</param>
        /// <returns>Encrypted string</returns>
        public static string Encrypt(string input, string password)
        {
 
            byte[] utfData = UTF8Encoding.UTF8.GetBytes(input);
            byte[] saltBytes = Encoding.UTF8.GetBytes(password);
            string encryptedString = string.Empty;
            using (AesManaged aes = new AesManaged())
            {
                Rfc2898DeriveBytes rfc = new Rfc2898DeriveBytes(password, saltBytes);
 
                aes.BlockSize = aes.LegalBlockSizes[0].MaxSize;
                aes.KeySize = aes.LegalKeySizes[0].MaxSize;
                aes.Key = rfc.GetBytes(aes.KeySize / 8);
                aes.IV = rfc.GetBytes(aes.BlockSize / 8);
 
                using (ICryptoTransform encryptTransform = aes.CreateEncryptor())
                {
                    using (MemoryStream encryptedStream = new MemoryStream())
                    {
                        using (CryptoStream encryptor = 
                            new CryptoStream(encryptedStream, encryptTransform, CryptoStreamMode.Write))
                        {
                            encryptor.Write(utfData, 0, utfData.Length);
                            encryptor.Flush();
                            encryptor.Close();
 
                            byte[] encryptBytes = encryptedStream.ToArray();
                            encryptedString = Convert.ToBase64String(encryptBytes);
                        }
                    }
                }
            }
            return encryptedString;
        }
 
        /// <summary>
        /// Decrypt a string
        /// </summary>
        /// <param name="input">Input string in base 64 format</param>
        /// <returns>Decrypted string</returns>
        public static string Decrypt(string input, string password)
        {
 
            byte[] encryptedBytes = Convert.FromBase64String(input);
            byte[] saltBytes = Encoding.UTF8.GetBytes(password);
            string decryptedString = string.Empty;
            using (var aes = new AesManaged())
            {
                Rfc2898DeriveBytes rfc = new Rfc2898DeriveBytes(password, saltBytes);
                aes.BlockSize = aes.LegalBlockSizes[0].MaxSize;
                aes.KeySize = aes.LegalKeySizes[0].MaxSize;
                aes.Key = rfc.GetBytes(aes.KeySize / 8);
                aes.IV = rfc.GetBytes(aes.BlockSize / 8);
 
                using (ICryptoTransform decryptTransform = aes.CreateDecryptor())
                {
                    using (MemoryStream decryptedStream = new MemoryStream())
                    {
                        CryptoStream decryptor = 
                            new CryptoStream(decryptedStream, decryptTransform, CryptoStreamMode.Write);
                        decryptor.Write(encryptedBytes, 0, encryptedBytes.Length);
                        decryptor.Flush();
                        decryptor.Close();
 
                        byte[] decryptBytes = decryptedStream.ToArray();
                        decryptedString = 
                            UTF8Encoding.UTF8.GetString(decryptBytes, 0, decryptBytes.Length);
                    }
                }
            }
 
            return decryptedString;
        }
    }
}

Post to Twitter

XAML Intellisense Stops Working in Visual Studio 2010

Today as I was working on a Silverlight application in Visual Studio 2010, XAML Intellisense just stopped working for me.  Quick internet search yielded no useful results, so I was to figure this out on my own.  Just to test I created a brand new application, and Intellisense was fine there.  Logical answer was that there was something wrong with my project.  I re-created the project, and slowly retraced my steps, testing XAML Intellisense  after each step.  The feature broke again as soon as I added a reference to  third party library I downloaded off the internet.  Something wrong with a file, obviously.  What I saw is that the DLL in question was blocked by Windows security.  I unblocked by right-clicking on the file in Windows explorer, going to properties and clicking Unblock button.

The package that I downloaded included many files, and I really hated to go through each one. Next internet search yielded a great solution from SysInternals.  You can download it here.  Once I got streams utility, I ran it on entire folder, and voila – Intellisense was back.  The command line is “streams –s –d ‘Folder with DLLs to Unblock’”, in my case “streams –s –d “c:\ThirdParty””

So, my research solved two problems for me – missing XAML Intellisense  and ability to unblock multiple files which is something I wanted to find an answer to a while ago,

Post to Twitter

Unit Testing Silverlight Applications – UI testing and Test Automation

In my last post I am going to cover the last two topics I set out to address.  The first topic is UI testing.  What unit test frameworks lack sometime is the actually UI testing.  What I mean by that is for example, click on a button, then see what happens.  In case of Silverlight, Silverlight framework itself has a number of helper classes to help us achieve this goal.  For example, ButtonAutomationPeer class allows us to drive button actions from within unit tests.  Also, Microsoft Silverlight unit testing framework allows developers to insert UI components onto unit testing surface.  Let me illustrate both concepts via an example.  Here is my code for such unit test”

[TestMethod]
[Asynchronous]
[Description("Asynch Get Companies in UI")]
[Tag("Asynch")]
public void TestUIGetCompanies()
{
 
    var companyVM = new CompanyModule.ViewModels.CompanyListViewModel(
        new Microsoft.Practices.Composite.Events.EventAggregator());
    CompanyListView companyV = new CompanyListView();
    companyV.DataContext = companyVM;
    TestPanel.Children.Add(companyV);
    ButtonAutomationPeer buttonPeer = 
        new ButtonAutomationPeer(companyV.FindName("GetCompaniesButton") as Button);
    DataGrid grid = companyV.FindName("CompanyGrid") as DataGrid;
    IInvokeProvider buttonInvoker = (IInvokeProvider)buttonPeer;
 
    IGridProvider gridPeer = new DataGridAutomationPeer(grid);
 
    EnqueueCallback(() => buttonInvoker.Invoke());
    EnqueueConditional(() => { return companyVM.CompanyList != null; });
    EnqueueCallback(
        () => Assert.IsTrue(companyVM.CompanyList.Count() > 0, "Should have data"),
        () => Assert.IsTrue(grid.Columns.Count == 3, "Should have 3 columns"),
        () => Assert.IsTrue(gridPeer.RowCount > 0, "Should have rows"));
    EnqueueTestComplete();
}

 

Let’s trace down what is going on in this test.  First of all, I am creating view model class.  Since I do not have a bootstrapper, I manually create EventAggregator myself.  Next, I am create a view to put my view model into.  I create view, then put my view model into the data context of my view.  Nest important step is to add my view to unit te3swt harness.  This is accomplished by adding my view to test panel.  My screenshot below illustrates where test panel is in terms of test runnier UI.  I added hand cursor to illustrate the test panel referred to in UI below as “Test Stage.”  As I run the unit tests, I will actually see my view there in the test stage.  Just like I added the view, I can remove it from test stage.

image

Next I am setting up code to invoke a button.  I am creating new instance of ButtonAutomationPeer class.  Of course, I need to find a button to attach the automation peer to, and I am using FindName method to find an i9nstance of my button.  To use this functionality I had to name my button.  Then, I am setting up an automation peer for my grid as well.  In general, most user input controls in Silverlight framework have matching automation objects.  In my case, I am testing the results of my button invocation directly against the grid, making sure that the grid has correct number of rows and columns.  I can also combine this type of testing with mocking,  Here is the unit test for this case:

[TestMethod]
[Asynchronous]
[Description("Asynch Get Companies in UI With Mocking")]
[Tag("Asynch")]
public void TestUIGetCompaniesWithMock()
{
    var companyVM = new Mock<ICompanyListViewModel>();
    companyVM.SetupGet(testVM => testVM.CompanyList).
        Returns(new ObservableCollection<Company>(new[] {
        new Company(){
            CompanyID = Guid.NewGuid(), DateAdded = DateTime.Now, CompanyName = "some random company"},
        new Company(){ 
            CompanyID = Guid.NewGuid(), DateAdded = DateTime.Now.AddDays(-1), CompanyName = "another company"}}));
    companyVM.SetupGet(testVM => testVM.GetCompaniesCommand).
        Returns(new DelegateCommand<object>((o) =>
        companyVM.Raise(vm => 
            vm.PropertyChanged += null, new System.ComponentModel.PropertyChangedEventArgs("CompanyList"))));
 
 
    CompanyListView companyV = new CompanyListView();
    companyV.DataContext = companyVM.Object;
    TestPanel.Children.Add(companyV);
    ButtonAutomationPeer buttonPeer = new ButtonAutomationPeer(companyV.FindName("GetCompaniesButton") as Button);
    DataGrid grid = companyV.FindName("CompanyGrid") as DataGrid;
    IInvokeProvider buttonInvoker = (IInvokeProvider)buttonPeer;
 
    IGridProvider gridPeer = new DataGridAutomationPeer(grid);
 
    EnqueueCallback(() => buttonInvoker.Invoke());
            
    EnqueueCallback(
        () => Assert.IsTrue(companyVM.Object.CompanyList.Count() > 0, "Should have data"),
        () => Assert.AreEqual(3, grid.Columns.Count, "Should have 3 columns"),
        () => Assert.AreEqual(2, gridPeer.RowCount, "Should have rows"));
    EnqueueTestComplete();
}

 

In the case above I am mocking property changed event by invoking it when a button is clicked, causing UI to re-bind.  The rest of testing code is very similar to actual invocation of server side code.

The last topic I would like to cover is StatLight framework.  You can take a closer look at the framework here.  This framework allows developers to invoke unit tests written with Microsoft unit testing framework for Silverlight from a command line and also read in results of such runs.  Once you download and unzip the DLLs into a folder, you will need to do one more thing – Unblock those DLLs in the properties of each file in Windows explorer.  Also, if you want to test server side code using StatLight, you will need to convert your web site to use local IIS inste4ad of Cassini (Visual Studio built-in IIS Server).  You will also need to put clientaccesspolicy.xml into the root of your IIS in order to avoid cross domain exceptions.  Using the StatLight framework is very simple.  Simply call StatLight.exe and pass XAP file on command line that contains your unit tests.  Here is a screenshot of what it looks like:

image 

As you can see, your –x parameter is the only one you have to specify to test.  You will also see that unit test is launched at the same time.  Now, to test results you have to add one more parameter – r.  Here is what that command would look like:

image

Once you run this, you will end up with out.txt in the specified folder.  Here is the content of this file:

image

The last parameter I want to mention is ability to limit test run by tag attribute I covered in an earlier post.  To user this feature, you have to add –t command line attribute like so:  Here is what this command line look like:

image

You can download complete solution here.

Thanks.

Post to Twitter

Windows Phone 7 Beta is here

Windows Phone 7 Developer tool beat has been released by Microsoft.  You can download it here.
Make sure to download and read release note available on the page above.

 

Thanks.

Post to Twitter

Unit Testing Silverlight Applications – Mocking

In this post I will explore ability to mock various Silverlight classes in order to enable mocking in your unit tests.  There is a variety of mocking frameworks available, but I will pick one for my testing – Moq.  You can download the framework here,  Once this is done, I need to add some references to my Silverlight unit test project.

Moq requires three assemblies available in the folder where Moq is installed:

image

If we are mocking view model or another object relying on Prism, we also need to add Prism references

image

Now we are ready to mock!

Let’s start by doing something simple.  I will mock my view model.  The only property I really want to test is my model property, which in my case exposes list of companies.  TO do so, I just need to setup property getter that contains my model.  The getter will be called when first accessed.  Here is what we have:

[TestMethod]
[Tag("Mocking")]
[Description("VM Mocking")]
public void TestMocking()
{
    var vm = new Mock<ICompanyListViewModel>();
    vm.SetupGet(testVM => testVM.CompanyList).
        Returns(new ObservableCollection<Company>(new[] {
            new Company()
                { CompanyID = Guid.NewGuid(), DateAdded = DateTime.Now, CompanyName = "some random company"},
            new Company()
                { CompanyID = Guid.NewGuid(), DateAdded = DateTime.Now.AddDays(-1), CompanyName = "another company"}}));
    Assert.AreEqual(2, vm.Object.CompanyList.Count, "Mocking failed");
 
}

 

I am only mocking view model in this case.  With Moq framework, as it is the case with most mocking frameworks, you are required to have interfaces in order to mock.  In case of RIA Services, this is an issue because client side classes are sealed and do not implement interfaces.  If you are using your own WCF service with custom classes, you can avoid this small issue.  You can also mock events as well.  This is how I would mock property changed event in my view model:

companyVM.SetupGet(testVM => testVM.GetCompaniesCommand).Returns(new DelegateCommand<object>((o) =>
    companyVM.Raise(vm => vm.PropertyChanged += null, new System.ComponentModel.PropertyChangedEventArgs("CompanyList"))));

 

As you can see, mocking is pretty easy concept, and the web page for Moq has quick start guide to help you get started.  Feel free to use a different mocking framework as well.  In the next post I will show how to unit test user interface using Silverlight unit testing framework.

Thanks

Post to Twitter

Unit Testing Silverlight Applications – Asynchronous Testing

In this post I will describe how to create asynchronous unit tests for Silverlight applications.  First of all, I’d like to point out that any communication with a server component in Silverlight must be asynchronous.  Reason being is that if communication was synchronous and the remote service was not responding, browser which host Silverlight application would lock up.  As you can see, asynchronous communication with a RIA Services WCF service is very important in our case. 

Let’s take a look on how to write a test that would assert that we can successfully get a list of companies from the server.  To do so, we must first take a look on how to write such a test.  This can be accomplished using asynchronous constructs available in Silverlight unit testing framework.  First of all, we have to change inheritance for our test class.  When you create a new test class, it does not inherit from any class, and we have to change this first of all.  Here is what old test class declaration look like:

[TestClass]
public class Tests

Here is what we are going to change it to:

[TestClass]
public class Tests : Microsoft.Silverlight.Testing.SilverlightTest

Now we must decorate our test method with appropriate attribute to signal to test running harness that it is about to execute asynchronous test:

[TestMethod]
[Asynchronous]
[Description("Asynch Get Companies")]
[Tag("Asynch")]
public void TestGetCompanies()

Now, let take a deeper look into framework itself to see the key methods that we can use in base class – SilverlightTest.

First one is EnqueueConditional.  This method is designed to let unit test wait until condition specified as an argument to EnqueueConditional is met.  It is very useful when you want to wait until a method call to the service is completed.  Here is how I would use this method:

        [TestMethod]
        [Asynchronous]
        [Description("Asynch Get Companies")]
        [Tag("Asynch")]
        public void TestGetCompanies()
        {
            bool isLoaded = false;
            Exception error = null;
            IEnumerable<Company> results = null;
            CompanyDomainContext context = new CompanyDomainContext(new Uri(@"http://localhost:4988/SilverlightTestingDemo-Web-CompanyDomainService.svc", UriKind.Absolute));
            var query = context.GetCompaniesQuery();
 
            context.Load<Company>(query, (result) =>
            {
                isLoaded = true;
                results = result.Entities;
                error = result.Error;
            }, null);
            EnqueueConditional(() => isLoaded);

 

What I am doing above is declaring a Boolean variable isLoaded that would signal to the framework to continue the test once data has been loaded.  I am setting this variable to true in the lambda expression callback that is called one server method’s execution is completed – (result)=> expression.

Next interesting method is EnqueueCallback.  This method simply declares multiple or in Action delegates that will be executed one they are popped off execution stack when harness processes test method calls.  What I mean is that the harness will execute all Action delegates that EnqueueCallback declares when it proceeds with running a test method once condition that  EnqueueConditional declares is met. If there are no such calls in the method body and there are no calls to EnqueueDelay that would also pause execution, then EnqueueCallback has no meaning, and asynchronous test essentially becomes synchronous.  Here is what we have so far:

        [TestMethod]
        [Asynchronous]
        [Description("Asynch Get Companies")]
        [Tag("Asynch")]
        public void TestGetCompanies()
        {
            
            bool isLoaded = false;
            Exception error = null;
            IEnumerable<Company> results = null;
            CompanyDomainContext context = new CompanyDomainContext(new Uri(@"http://localhost:4988/SilverlightTestingDemo-Web-CompanyDomainService.svc", UriKind.Absolute));
            var query = context.GetCompaniesQuery();
 
            context.Load<Company>(query, (result) =>
            {
                isLoaded = true;
                results = result.Entities;
                error = result.Error;
            }, null);
            EnqueueConditional(() => isLoaded);
            EnqueueCallback(
                () => Assert.IsTrue(results.Count() > 0, "Should have data"),
                () => Assert.IsNull(error, "Should have no errors"));

 

The last important method is EnqueueTestComplete.  This method puts Test Completed signal onto the execution stack. This method is typically the very last statement of the test method body.  Here is our final version of the method:

        [TestMethod]
        [Asynchronous]
        [Description("Asynch Get Companies")]
        [Tag("Asynch")]
        public void TestGetCompanies()
        {
            
            bool isLoaded = false;
            Exception error = null;
            IEnumerable<Company> results = null;
            CompanyDomainContext context = new CompanyDomainContext(new Uri(@"http://localhost:4988/SilverlightTestingDemo-Web-CompanyDomainService.svc", UriKind.Absolute));
            var query = context.GetCompaniesQuery();
 
            context.Load<Company>(query, (result) =>
            {
                isLoaded = true;
                results = result.Entities;
                error = result.Error;
            }, null);
            EnqueueConditional(() => isLoaded);
            EnqueueCallback(
                () => Assert.IsTrue(results.Count() > 0, "Should have data"),
                () => Assert.IsNull(error, "Should have no errors"));
            EnqueueTestComplete();
        }

 

You can download the complete code here.  In the next post I will cover mocking for synchronous and asynchronous unit tests.

Thanks..

Post to Twitter

Unit Testing Silverlight Applications

I am starting a short series of posts on unit testing of Silverlight applications.  I will be using the following set of technologies. 

  • Microsoft Silverlight Unit testing framework that ships with Silverlight tool kit
  • Moq – mocking framework that supports Silverlight 4
  • StatLight – unit testing automation framework that will allow for unattended / automated running unit tests

I am going to start with a simple Silverlight application that is using RIA services and Prism.  First things first, let’s create unit test project.  Project template will be installed when you install the Silverlight toolkit.  Here is what add project dialog looks like.  The template is located under Silverlight tab

image

Here are the setting for the next dialog:

image

Once project is created, a simple test class is also created.  If you ever worked with Microsoft unit testing in Visual Studio, you will find the API quite familiar, including all key classed, attributes and namespaces.  I am going to create a simple synchronous test first, testing my RIA services class to ensure that validation rules are setup properly.  To do so, I first add a reference to my simple Company module to my Silverlight unit test project.  Since I am also testing RIA services classes, I will add two more references: System.ComponentModel.DataAnnotations and System.ServiceModel.DomainServices.Client.dll.  Now with this our of the way, here is what my test class and method look like:

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Silverlight.Testing;
using System.Collections.ObjectModel;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SilverlightTestingDemo.Web;
 
namespace SilverlightUnitTest
{
    [TestClass]
    public class Tests
    {
        [TestMethod]
        [Tag("Synch")]
        [Description("Rules")]
        public void TestCompanyRules()
        {
            Company company = new Company();
            company.CompanyName = "test";
            Assert.AreEqual(0, company.ValidationErrors.Count, "Should be valid");
            company.CompanyName = string.Empty;
            Assert.AreEqual(1, company.ValidationErrors.Count, "Should be in valid");
        }
    }
}

 

Let me go over the attributes I used.  TestClass attribute is what signals to Unit testing framework as to what classes contain unit tests.  TestMethod attribute identifies methods that represent a single unit test.  Tag attribute is used by unit test runner UI to filter out what tests based on attributes will be run.  Description attribute data will be shown in runner UI when unit tests are run. Assert class is used to assert test results.  For example, in my first Assert statement I make sure that Company instance is valid once name is set.

When I run unit tests after setting up unit test application’s web site as start up project, here is what I see.

image

Test are setup to auto-run by default.  You will see the countdown label, and if you click on count down label, you will have a chance to select specific tests to run.

image

After tests are run, you will see test run summary in the top left cornet of the screen.  In my case I see that I had total of 1 test, and 2 test has passed.  if a test fails, you will see that in the test run summary.  You can download solution so far here.  In my next post I will cover asynchronous testing in Silverlight application.

Thanks.

Post to Twitter

Implementing Double-Click In Silverlight DataGrid

As I was working on one of my presentations, I wanted to go to a detail from from query form by letting user double-click.  No standard Silverlight controls implement double-clicks, and this includes DataGrid.  So, naturally one would need to listen to click events and interpret clicks within a certain time to be a double-click.  In my case I will use 300 milliseconds.  Another fact to consider is that if you try to do hook up double-click to the DataGrid itself, you will be disappointed because LeftMouseButtonUp event only fires when there are no rows to get in the way.  So, to make this work we will have to use each row’s mouse events.  I am going to wrap this up in a behavior first.  I am going to call this behavior  DataGridMouseLeftButtonDownCommandBehavior.  Here is what my class looks like, and it is very simple.  As you see, I am inheriting from CommandBase from Prism (Composite Application Guidance for Silverlight/WPF).

using System;
using Microsoft.Practices.Composite.Presentation.Commands;
using System.Windows.Controls;
using System.Windows.Input;
 
namespace CompanyModule.Converters
{
    /// <summary>
    /// Inherit from command base from Prism
    /// </summary>
    public class DataGridMouseLeftButtonDownCommandBehavior : CommandBehaviorBase<DataGrid>
    {
        /// <summary>
        /// Last time mouse was clicked
        /// </summary>
        private DateTime _lastTime;
 
        /// <summary>
        /// Number of milliseconds to interpret as doible-click
        /// </summary>
        private const long MillisesondsForDoubleClick = 300;
 
        /// <summary>
        /// Create new instance
        /// </summary>
        /// <param name="dataGrid">DataGrid to attach behavior to</param>
        public DataGridMouseLeftButtonDownCommandBehavior(DataGrid dataGrid)
            : base(dataGrid)
        {
            dataGrid.LoadingRow += OnLoadingRow;
            dataGrid.UnloadingRow += OnUnloadingRow;
        }
 
        /// <summary>
        /// Hook up mouse events
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnUnloadingRow(object sender, DataGridRowEventArgs e)
        {
            e.Row.MouseLeftButtonUp -= OnMouseLeftButtonDown;
        }
 
        /// <summary>
        /// Unhook events to avoid memory leaks
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnLoadingRow(object sender, DataGridRowEventArgs e)
        {
            e.Row.MouseLeftButtonUp += OnMouseLeftButtonDown;
        }
 
 
        private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            // if timing is right, fire command
            if ((DateTime.Now.Subtract(_lastTime).TotalMilliseconds) < MillisesondsForDoubleClick)
            {
                ExecuteCommand();
            }
            // reset the time
            _lastTime = DateTime.Now;
        }
    }
}

 

Now that we have behavior of the way, we need to come up with a clean way to hook it up as well as setting a command and command parameter onto a DataGrid.

I am going to use a static class and attached properties.  Attached properties are a feature of Silverlight that would allow us to set properties on one object via properties defined on another object.  Most common example of them is Grid control in Silverlight.  If you add a child control to a Grid, you set its location by using Grid.Column or Grid.Row on child control itself, such as Textbox.  Properties that I am going to need are Command and CommandParameter as well as a property I can attach my behavior to.  I am again using Prism for my project.  Here is what my attached properties look like:

    public static class DataGridDoubleClick
    {
        private static readonly DependencyProperty DataGridDoubleClickCommandBehaviorProperty = 
            DependencyProperty.RegisterAttached(
                "DataGridDoubleClickCommandBehavior",
                typeof(DataGridMouseLeftButtonDownCommandBehavior),
                typeof(DataGridDoubleClick),
                null);
 
        public static readonly DependencyProperty CommandProperty = 
            DependencyProperty.RegisterAttached(
                "Command",
                typeof(ICommand),
                typeof(DataGridDoubleClick),
                new PropertyMetadata(OnSetCommand));
 
        public static readonly DependencyProperty CommandParameterProperty = 
            DependencyProperty.RegisterAttached(
               "CommandParameter",
               typeof(object),
               typeof(DataGridDoubleClick),
               new PropertyMetadata(OnSetCommandParameter));

 

I am defining call backs in order to be able to attach my behavior to the DataGrid in those.  The reason I cannot just put behavior inside XAML is because I need to pass DataGrid to my behavior as a parameter.  I am using attached property for the behavior because this makes it easy to store in static environment.

Here is how I am hooking up behavior in call back methods.


        private static void OnSetCommand
            (DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            DataGrid dataGrid = dependencyObject as DataGrid;
            if (dataGrid != null)
            {
                DataGridMouseLeftButtonDownCommandBehavior behavior = GetBehavior(dataGrid);
                behavior.Command = e.NewValue as ICommand;
            }
        }
 
        private static void OnSetCommandParameter
            (DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            DataGrid dataGrid = dependencyObject as DataGrid;
            if (dataGrid != null)
            {
                DataGridMouseLeftButtonDownCommandBehavior behavior = GetBehavior(dataGrid);
                behavior.CommandParameter = e.NewValue;
            }
        }

 

The final part is how to set the behavior.  Here is the short method for it:

        private static DataGridMouseLeftButtonDownCommandBehavior GetBehavior(DataGrid dataGrid)
        {
            DataGridMouseLeftButtonDownCommandBehavior behavior =
                dataGrid.GetValue(DataGridDoubleClickCommandBehaviorProperty) 
                    as DataGridMouseLeftButtonDownCommandBehavior;
            if (behavior == null)
            {
                behavior = new DataGridMouseLeftButtonDownCommandBehavior(dataGrid);
                dataGrid.SetValue(DataGridDoubleClickCommandBehaviorProperty, behavior);
            }
            return behavior;
        }

 

Now the final step – XAML for my data grid:

<UserControl
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
   xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
   xmlns:my="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"  
   xmlns:command="clr-namespace:Microsoft.Practices.Composite.Presentation.Commands;
           assembly=Microsoft.Practices.Composite.Presentation"

   xmlns:converters="clr-namespace:CompanyModule.Converters"
   xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
   x:Class="CompanyModule.Views.CompanyListView"
   mc:Ignorable="d"
   d:DesignHeight="300" d:DesignWidth="400">
    <UserControl.Resources>
        <converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
    </UserControl.Resources>
    <Grid x:Name="LayoutRoot" Background="White" HorizontalAlignment="Stretch">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Button Content="Get Companies" command:Click.Command="{Binding GetCompaniesCommand}"/>
        <my:DataGrid 
           Grid.Row="1" 
           ItemsSource="{Binding CompanyList}" 
           HorizontalAlignment="Stretch"
           converters:DataGridDoubleClick.Command="{Binding Path=DoubleClickCommad}"
           converters:DataGridDoubleClick.CommandParameter="{Binding RelativeSource={RelativeSource Self},
             
Path=SelectedItem}"
           SelectionMode="Single">
           
        </my:DataGrid>
        <Rectangle Grid.RowSpan="2" 
                  Fill="LightBlue" 
                  Visibility="{Binding IsBusy, Converter={StaticResource BooleanToVisibilityConverter}}" 
                  Opacity="0.3"/>
    </Grid>
</UserControl>

 

Here is what my command looks like in ViewModel:

public DelegateCommand<object> DoubleClickCommad { get; private set; }

DoubleClickCommad = new DelegateCommand<object>(SelectCompanyForEdit);

 

private void SelectCompanyForEdit(object load)
{
  if (load != null && load is Company)
    {
      MessageBox.Show(((Company)load).CompanyName);
    }
}

 

And that is all there is to it.

Thanks.

Post to Twitter

First Stab at Reactive Framework

Today I made an attempt to make some sense of Reactive Framework(Rx).  Rx allows developers to write queries against events.  I know, I had hard time wrapping my head around this concept as well.  I hope the example below will help.

I downloaded and installed Rx extensions for Silverlight from the page above.  I created new Silverlight project and added references to three DLLs that are included with Rx:

System.CoreEx, System.Observable, System.Reactive.

In attempt to save time I created RIA Services project.  Rx is not as good of a fit for the Rx pattern, so my example is a bit contrived.

First, I am creating new instance of domain context

RXContext context;

Now, I am creating new query and starting the load for it:

            var talks = context.GetTalksQuery();


            var op = context.Load<Talk>(talks, LoadBehavior.RefreshCurrent, false);

Now, the fun part:  I am creating two event handlers by querying completed event with two different where clauses – one for error, the other for success:


    var events = Observable.FromEvent((EventHandler<EventArgs> eventInstance) =>
        new EventHandler(eventInstance),
            eventInstance => op.Completed += eventInstance,
            eventInstance => op.Completed -= eventInstance);
    var subsc = events.Where(ev => op.Error == null).Subscribe((args) =>
        { gridTalks.ItemsSource = op.AllEntities; });
    var errorSubs = events.Where(ev => op.Error != null).Subscribe((args) =>
        { MessageBox.Show(op.Error.ToString()); });

In the first statement I am converting regular event to observable event.  In the other two statement I am creating two event subscriptions with different where clauses.

Rx supports other clauses, such as group by as well.  I can see that Rx in general can result in cleaner, more readable code.  You can find more details at this Rx 101 page.

Post to Twitter

Tool Tip Usage in Silverlight Application

I have not blogged in a month.  What I found out in that time is that working 60-70 hours a week on two separate projects with deadlines is not very conducive to blogging :-).  Now that I am off one of the projects, I should have more time to get into the routine of blogging weekly which has been my goal for a while.

Tooltips are pretty common in business applications.  They save real estate on the screen for developers.  They also provide users with ability to see more details without any button clicks.

It is very easy to setup a simple tool tip.  Here is a quick example:

        <TextBox 
           TextWrapping  ="Wrap" 
           Text="{Binding Path=CurrentPerson.FirstName}" 
           d:LayoutOverrides="Width, Height" 
           Grid.Column="1" 
           ToolTipService.ToolTip="{Binding Path=CurrentPerson.FullName}"/>

In this example I am binding text of a TextBox to FirstName of my person class.  Here is what my person class looks like:

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Media.Imaging;

namespace SilverlightToolTipDemo
{
    public class Person
    {
        public Person()
        {
            LastName = "Barskiy";
            FirstName = "Sergey";
            FullName = "Mr. Sergey Barskiy";
            Occupation = "Programmer";
            MaritalStatus = "Married";
            BitmapImage image = new BitmapImage(new Uri("../Images/Sergey_Barskiy.jpg", UriKind.RelativeOrAbsolute));
            Photo = image;

        }

        public string LastName { get; set; }
        public string FirstName { get; set; }
        public string FullName { get; set; }
        public string Occupation { get; set; }
        public string MaritalStatus { get; set; }
        public ImageSource Photo { get; set; }


    }
}

This looks pretty boring though.  Too much like old WinForms :-).

Let’s now use Silverlight capabilities and jazz it up a bit.

In the simple case you can just assign a string to tool tip and it will be shown on mouse-over event.  However, ToolTip property of ToolTipService can do a lot more.  You can put a control inside of it!  In my case, I want to show full name, photo, occupation and martial status.  Sounds complicated?  It is not.  Here is what it should look like:

        <TextBox
            Text="{Binding Path=CurrentPerson.LastName}"
            Grid.Column="1"
            d:LayoutOverrides="Width, Height"
            Grid.Row="1">
            <ToolTipService.ToolTip>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition/>
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="Auto"/>
                    </Grid.RowDefinitions>
                    <Image
                        Source="{Binding Path=CurrentPerson.Photo}"
                        Grid.ColumnSpan="2"
                        Grid.Row="0"
                        Width="100"
                        Height="100"
                        Stretch="UniformToFill"/>
                    <TextBlock
                        Grid.Row="1"
                        Text="Full Name:"
                        d:LayoutOverrides="Width, Height"
                        HorizontalAlignment="Right"
                        VerticalAlignment="Center"/>
                    <TextBlock
                        Grid.Row="1"
                        Text="{Binding Path=CurrentPerson.FullName}"
                        d:LayoutOverrides="Width, Height"
                        HorizontalAlignment="Left"
                        VerticalAlignment="Center"
                        Grid.Column="1"/>
                    <TextBlock
                        Text="Occupaton:"
                        d:LayoutOverrides="Width, Height"
                        HorizontalAlignment="Right"
                        VerticalAlignment="Center"
                        Grid.Row="2"/>
                    <TextBlock
                        Text="{Binding Path=CurrentPerson.Occupation}"
                        d:LayoutOverrides="Width, Height"
                        HorizontalAlignment="Left"
                        VerticalAlignment="Center"
                        Grid.Column="1"
                        Grid.Row="2"/>
                    <TextBlock
                        Text="Marital Status:"
                        d:LayoutOverrides="Width, Height"
                        HorizontalAlignment="Right"
                        VerticalAlignment="Center"
                        Grid.Row="3"/>
                    <TextBlock
                        Text="{Binding Path=CurrentPerson.MaritalStatus}"
                        d:LayoutOverrides="Width, Height"
                        HorizontalAlignment="Left"
                        VerticalAlignment="Center"
                        Grid.Column="1"
                        Grid.Row="3"/>
                </Grid>
            </ToolTipService.ToolTip>
        </TextBox>

Pretty easy, hah?  When I move my mouse over this textbox, I will see my photo along with additional information:

image

You can download full sample application here.

Thanks.

Post to Twitter

ReMix Talk

As I posted previously, I talked at Atlanta ReMix 2010 conference past Saturday.  Entire event was a a success, we had over 200 people there.  We had great presenters and good topics.  My topic was “Microsoft Silverlight and Windows Azure: A Match Made for the Web”

You can download PowerPoint presentation here.  You can download solution here.  To get solution up and going, you need to have Visual Studio 2010 installed, along with Silverlight 4 tools and Azure tools.  You will also need to sign up for an account on Azure and SQL Azure.  You will need to update web.config file and ServiceReference.ClientConfig file.

Please let me know if you have any questions.

Thank you.

Post to Twitter

ElementName Binding Inside Silverlight DataGrid

If you ever used ComboBox inside a templated columns inside DataGrid in Silverlight, you probably encountered the following issue. 

If you use ElementName to bind ItemsSource for a ComboBox in this situation, you will find that ElementName cannot be resolved.  Typically, you have to put your items source inside Resources collection on your use control, and use binding with StaticResource.  This is quite a pain, especially if you are using MVVM pattern, such as Prism.  This problems has been a sore spot for me for a while, but I did not have time to come up with a good solution.

Today I gave it some thought, and it hit me.  I should use a behavior to solve the problem.  The approach I took is manually look for the bound element one the ComboBox is part of visual tree.  I can do this inside Loaded event.  Here is how I got started:

    public class ResolveElementName : TargetedTriggerAction<FrameworkElement>

    {

        protected override void OnAttached()

        {

            base.OnAttached();

            Target.Loaded += Target_Loaded;

        }

 

        protected override void OnDetaching()

        {

            base.OnDetaching();

            Target.Loaded -= Target_Loaded;

        }

 

        private void Target_Loaded(object sender, RoutedEventArgs e)

        {

I also added a Dependency Property:

        public string PropertyName

        {

            get { return (string)GetValue(PropertyNameProperty); }

            set { SetValue(PropertyNameProperty, value); }

        }

 

        public static readonly DependencyProperty PropertyNameProperty =

            DependencyProperty.Register("PropertyName", typeof(string), typeof(ResolveElementName), new PropertyMetadata(string.Empty));

 

        protected override void Invoke(object parameter)

        {

            // do nothing

        }

 

The next step is to look how I typically setup ComboBox inside data gird.  I would like to keep the code as close to usual setup as possible to minimize the learning of new functionality.  Here is XAML from my test program.  This also shows how behavior is setup.

        <grid:DataGrid

            ItemsSource="{Binding People}"

            x:Name="PoepleBox"

            Grid.Row="3"

            AutoGenerateColumns="False" >

            <grid:DataGrid.Columns>

                <grid:DataGridTemplateColumn>

                    <grid:DataGridTemplateColumn.CellTemplate>

                        <DataTemplate>

                            <TextBlock Text="{Binding Path=Name}" Margin="7"/>

                        </DataTemplate>

                    </grid:DataGridTemplateColumn.CellTemplate>

 

                </grid:DataGridTemplateColumn>

                <grid:DataGridTemplateColumn>

                    <grid:DataGridTemplateColumn.CellTemplate>

                        <DataTemplate>

                            <TextBlock

                                Text="{Binding Path=StatusID}"

                                Margin="7"/>

                        </DataTemplate>

                    </grid:DataGridTemplateColumn.CellTemplate>

 

                </grid:DataGridTemplateColumn>

                <grid:DataGridTemplateColumn>

                    <grid:DataGridTemplateColumn.CellTemplate>

                        <DataTemplate>

                            <ComboBox

                                SelectedValue="{Binding Path=StatusID, Mode=TwoWay}"

                                DisplayMemberPath="StatusName"

                                SelectedValuePath="StatusID"

                                ItemsSource="{Binding ElementName=LayoutRoot, Path=DataContext.Statuses}" 

                                Margin="7"

                                Width="200" >

                                <i:Interaction.Triggers>

                                    <i:EventTrigger>

                                        <behavior:ResolveElementName PropertyName="ItemsSource" />

                                    </i:EventTrigger>

                                </i:Interaction.Triggers>

                            </ComboBox>

                        </DataTemplate>

                    </grid:DataGridTemplateColumn.CellTemplate>

 

                </grid:DataGridTemplateColumn>

            </grid:DataGrid.Columns>

        </grid:DataGrid>

Also, you will need to import name spaces to get this to work as following:

<UserControl x:Class="ResolveElementNameBehaviorDemo.MainPage"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

    xmlns:local="clr-namespace:ResolveElementNameBehaviorDemo"

    xmlns:grid="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"

    xmlns:behavior="clr-namespace:ResolveElementNameBehavior;assembly=ResolveElementNameBehavior"

    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"  

 

Now, I would like to show you how I am updating ItemsSource binding by replacing element name binding with regular source based binding:

        private void Target_Loaded(object sender, RoutedEventArgs e)

        {

 

            if (Target != null)

            {

                var fields = Target.GetType().GetFields(

                    System.Reflection.BindingFlags.Public |

                    System.Reflection.BindingFlags.FlattenHierarchy |

                    System.Reflection.BindingFlags.Static);

                foreach (var field in fields)

                {

                    if (field.FieldType == typeof(DependencyProperty) &&

                        (field.Name == PropertyName ||

                        field.Name == string.Concat(PropertyName, "Property")))

                    {

                        DependencyProperty dp = field.GetValue(Target) as DependencyProperty;

                        var binding = Target.GetBindingExpression(dp);

                        string elementName = binding.ParentBinding.ElementName;

                        if (!string.IsNullOrEmpty(elementName))

                        {

                            DependencyObject boundToElement = GetElementBasedOnName(Target, elementName);

                            if (boundToElement != null)

                            {

                                Binding newBinding = new Binding();

                                Binding oldBinding = binding.ParentBinding;

                                newBinding.BindsDirectlyToSource = oldBinding.BindsDirectlyToSource;

                                newBinding.Converter = oldBinding.Converter;

                                newBinding.ConverterCulture = oldBinding.ConverterCulture;

                                newBinding.ConverterParameter = oldBinding.ConverterParameter;

                                newBinding.FallbackValue = oldBinding.FallbackValue;

                                newBinding.Mode = oldBinding.Mode;

                                newBinding.NotifyOnValidationError = oldBinding.NotifyOnValidationError;

                                newBinding.Path = oldBinding.Path;

                                newBinding.Source = boundToElement;

                                newBinding.StringFormat = oldBinding.StringFormat;

                                newBinding.TargetNullValue = oldBinding.TargetNullValue;

                                newBinding.UpdateSourceTrigger = oldBinding.UpdateSourceTrigger;

                                newBinding.ValidatesOnDataErrors = oldBinding.ValidatesOnDataErrors;

                                newBinding.ValidatesOnExceptions = oldBinding.ValidatesOnExceptions;

                                newBinding.ValidatesOnNotifyDataErrors = oldBinding.ValidatesOnNotifyDataErrors;

                                if (Target is ComboBox)

                                {

                                    ComboBox combo = Target as ComboBox;

                                    combo.SetBinding(dp, newBinding);

                                    combo.SetBinding(ComboBox.SelectedValueProperty,

                                        combo.GetBindingExpression(ComboBox.SelectedValueProperty).ParentBinding);

                                }

                                else

                                {

                                    Target.SetBinding(dp, newBinding);

                                }

                               

                            }

                        }

                    }

                }

            }

        }

 

Last step, let me show you how to look for an element with a specific name inside visual tree.  I will use a recursive function that will use VisualTreeHelper class:

        private static DependencyObject GetElementBasedOnName(DependencyObject startPoint, string elementName)

        {

            DependencyObject returnValue = null;

            if (startPoint != null)

            {

                DependencyObject parent = VisualTreeHelper.GetParent(startPoint);

                if (parent != null)

                {

                    FrameworkElement fe = parent as FrameworkElement;

                    if (fe != null)

                    {

                        if (fe.Name == elementName)

                        {

                            returnValue = fe;

                        }

                        else

                        {

                            returnValue = GetElementBasedOnName(fe, elementName);

                        }

                    }

                    else

                    {

                        returnValue = GetElementBasedOnName(fe, elementName);

                    }

                }

            }

            return returnValue;

        }

 

This is it.  There as couple of downsides of this approach.  First of all, there is a small flash when combo is bound.  It is hard to notice though.  The other downside is the overhead of looking for a parent.  However, this is not visibly noticeable.  I tested with a data grid with 100 items, and I do not see any hesitation when scrolling.

You can download the entire solution with behavior and test application here.

I also published it to Microsoft Expression Gallery.

Please let me know if you have any questions.. 

Post to Twitter

Windows Phone 7 Database

I just uploaded and published new CodePlex project I have been working on.  It is an Isolated Storage based database for Windows Phone 7.  I converted my existing Silverlight database project I published a long time ago and adapted it to Windows Phone 7. It supports multiple strongly typed tables, basic Linq based operations, addition and deletion of ranges of items, deletion of items based on condition.  You can also directly bind data to UI in Silverlight because base table inherits from ObservableCollection.  It supports encryption along with lazy loading of table. 

Please take a look at http://winphone7db.codeplex.com/

 

Here are key classes of the project.  ITable interface makes it easy to write generic code in Database class.  It is a simple interface as you can see:

using System;
using System.IO;

namespace SilverlightPhoneDatabase.Core
{
    /// <summary>
    /// Interface that is used for tables in a database
    /// </summary>
    public interface ITable
    {
        /// <summary>
        /// Type of object that database contains
        /// </summary>
        Type RowType { get; }

        /// <summary>
        /// Save table le to the Isolated Storage
        /// </summary>
        void Save();

        /// <summary>
        /// Write content of a table to a file stream
        /// </summary>
        /// <param name="stream">Stream to write table to</param>
        void WriteDTableToStream(Stream stream);

        /// <summary>
        /// Set internal variables data when a table is de-serialized
        /// </summary>
        /// <param name="databaseName">Database name that table belongs to</param>
        /// <param name="password">Password to use for encryption</param>
        void SetTableDefinition(string databaseName, string password);
    }
}

I use XML Serializer to store table to Isolated Storage:

using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
                    {
                        string fileName = string.Concat(_databaseName, ".", typeof(T).FullName);
#if SILVERLIGHT
                        if (store.FileExists(fileName))
                        {
                            store.DeleteFile(fileName);
                        }
#else
                        if (store.GetFileNames(fileName).Length > 0)
                        {
                            store.DeleteFile(fileName);
                        }
#endif
                        using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(fileName, FileMode.OpenOrCreate, store))
                        {
                            WriteDTableToStream(stream);
                        }
                    }

 

Writing data to stream is very easy:

 /// <summary>
        /// Write content of a table to a stream
        /// </summary>
        /// <param name="stream">Stream to write table to</param>
        public void WriteDTableToStream(Stream stream)
        {
            string content = string.Empty;
            using (StringWriter stringWriter = new StringWriter())
            {
                XmlSerializer serializer = new XmlSerializer(this.GetType());

                serializer.Serialize(stringWriter, this);
                stringWriter.Flush();
                content = stringWriter.GetStringBuilder().ToString();
                if (!string.IsNullOrEmpty(_password))
                {
                    content = Cryptography.Encrypt(content, _password);
                }
                stringWriter.Close();
            }

            using (StreamWriter writer = new StreamWriter(stream))
            {
                writer.Write(content);
                writer.Flush();
                writer.Close();
            }
        }

The most interesting part of Database class is probably table loading.  This is done via generic function Table<T>:

/// <summary>
        /// FInd instance of a table that contains specific row type
        /// </summary>
        /// <typeparam name="T">Type of object that this table contains</typeparam>
        /// <returns></returns>
        public Table<T> Table<T>()
        {
            ITable returnValue = (from oneTable in Tables
                                  where oneTable.RowType == typeof(T)
                                  select oneTable).FirstOrDefault();
            if (_useLazyLoading && !_loadedTables[typeof(T)])
            {
                Type tableType = typeof(Table<>).MakeGenericType(new Type[] { typeof(T) });
                string fileName = string.Concat(_databaseName, ".", typeof(T).FullName);
                using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
                {
                    using (IsolatedStorageFileStream tableStream = new IsolatedStorageFileStream(fileName, FileMode.Open, store))
                    {
                        LoadTable(tableStream, tableType);
                        tableStream.Close();
                    }
                }
                _loadedTables[typeof(T)] = true;
                returnValue = (from oneTable in Tables
                               where oneTable.RowType == typeof(T)
                               select oneTable).FirstOrDefault();
            }
            return (Table<T>)returnValue;

        }

 

I would very much appreciate comments and feature requests related to this project.

Thanks in advance for the feedback.

Post to Twitter

ReMix 2010 in Atlanta

If you have not registered for this fine event I blogged about previously, you have a week left.

You can register for it here: http://reMIXatlanta.org.  You can also check out the list of session that will be presented there.

Yours truly will be presented a session there as well.  The title will be “Microsoft Silverlight and Windows Azure: A Match Made for the Web”.

Here is what they session is about:

By combining the rich user experience of Silverlight with the scalability of Windows Azure compute and storage, you can build some incredible end-to-end web applications. In this session we will discuss the business advantages of running Silverlight applications in the cloud. We will cover the steps necessary to build Silverlight applications for deployment in Azure including: data access with SQL Azure, cloud storage, communication mechanisms and data access options. We will also demonstrate how the same approach works for Windows Phone 7 development.

I am just as excited about speaking as I am about attending other sessions.  One can always learn a ton at the community events.

Post to Twitter

Windows 7 and IIS Errors

I just re-installed Windows 7 on my machine.  Once I opened and tried to run an old web project configured for VS 2010 and .NET 4.0, my IIS server threw an exception.  I went into Windows features and enabled all IIS features related to ASP.NET and WCF.  Even after all this I still got the following error:

HTTP Error 500.21 – Internal Server Error
Handler "PageHandlerFactory-Integrated" has a bad module "ManagedPipelineHandler" in its module list

I checked web.config, and it looked correct, plus it has not changed in a while.  After some research I found out that  even though ASP.NET 4.0 was showing up in properties of my virtual directory, ASP.NET still did not function properly.  The solution was to run aspnet_regiis –i after all.  One thing to remember is to run this utility from Microsoft.NET v4 folder, not 2.0 folder.  Once I ran the utility, I was back in business.

 

I hope this helps someone with the same issue.

Post to Twitter

reMix Atlanta 2010

image

Mark your calendar and purchase your ticket now for Atlanta’s premiere Design & Developer Event

THE WEB BELONGS TO US, AND MOBILE WILL BE NEXT.

reMIX LOCATION

Saturday May 8th 8:00AM-5:00PM

Atlanta Marriott Perimeter Center

246 Perimeter Center Pkwy NE

Atlanta, Georgia 30346

Phone: 770-394-6500

reMIX Atlanta is the one-day conference for developers and designers who want to take their skills to the next level. Come out to see the exciting new technologies and techniques that can be used to build the next generation of interactive websites and mobile applications.

This is a “Don’t Miss Event” with only 400 seats. Get yours today!

REGISTER TODAY!

http://reMIXatlanta.org

Tickets only $25 until 4/27, then $35

Limited seating, filling fast! Act Now!

SPECIAL BONUS

A very awesome FREE pre-event:

Friday May 7th 6:00PM-9:00PM

Hosted by Carl & Richard, this is a .NET Rocks! fun evening about Visual Studio 2010 & .NET 4

image

http://dotnetrocks.com

 

What to Expect:

Learn about the completely new Windows Phone 7 and the excitement about quickly developing applications using Silverlight and building 2D/3D games using XNA.

Learn about the Designer/Developer workflow used to create great user experience (UX) in your applications.

Learn about building next-generation web applications with the new Silverlight 4 features, how to build with Windows Azure, and the improved ASP.NET MVC 2.0

image

Post to Twitter

Metro Icons for Windows Phone 7

I found this link that will allow you to download set of Metro icons for Windows Phone 7.  You will need to scroll down closer to the bottom of the page to find the actual links.

Enjoy

Post to Twitter

Atlanta .NET Talk on Windows Phone 7

I had a privilege to present on Silverlight development for Windows Phone 7 at local Atlanta.NET Users Group today, March 29th 2010.

You can download PowerPoint presentation here.  Please email me any questions you have regarding the presentation.

Thanks.

Post to Twitter

Windows Phone 7 Application with OData

In this post I will continue exploring Windows Phone 7 development.  Almost any application needs a data source.  There are a few options available for Silverlight applications on Windows Phone.  You can use plain WCF service.  You can optionally put it on Azure.  You can also use Isolated Storage.  Essentially it becomes your custom database.  Of course, you have to write all the API in this case.  Or, you can use OData.  OData approach is the one I am exploring in this post.

First things first, you need to download CTP for OData on Windows Phone.  Here is the link for this download:

http://www.microsoft.com/downloads/details.aspx?FamilyID=b251b247-70ca-4887-bab6-dccdec192f8d&displaylang=en

Download and unzip the files into a folder.  You will need a DLL that is contained in this download – System.Data.Services.Client.Dll

You can follow my previous post and create new Silverlight application for Windows Phone.  There is small change you will need to make.  You need to select the following project template:

image

Now we need to pick an OData source.  I am going to look at www.OData.Org to find one.  I am picking Mix 2010, but you can select any other.  Here is the link I found on OData site – http://api.visitmix.com/OData.svc/

You can always browse the service.  In my case I am going to generate a proxy for this service by running the following command from Microsoft.NET/v4 directory on your local machine:

DataSvcutil.exe /uri:http://api.visitmix.com/OData.svc /DataServiceCollection /Version:2.0 /out:VisitMixClientTypes.cs

DataSvcuil is the .NET utility that generates proxies for ADO.NET Data Services or OData.

Once this is done, copy generated file (VisitMixClientTypes.cs) into the project folder and include it in the project.  What we have inside the file is the proxy for OData service.

Nest step is to update the XAML to match our proxy.  In my simple example I will use the list of sessions and show it on the front page.  Here is what my XAML looks like for my main page (MainPage.xaml)

 

 

<!--ContentGrid contains ListBox. Place additional content here-->
<Grid x:Name="ContentGrid" Grid.Row="1">
    <Grid.Projection>
        <PlaneProjection/>
    </Grid.Projection>
    <ListBox x:Name="ListBoxOne" MouseLeftButtonUp="ListBoxOne_MouseLeftButtonUp"
             Style="{StaticResource PhoneListBox}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel x:Name="DataTemplateStackPanel" Orientation="Horizontal">
                    <Border x:Name="DataTemplateBorder" Height="44" Width="44" BorderBrush="White"
                            BorderThickness="2.5" CornerRadius="100" Margin="10,16,0,0"
                            VerticalAlignment="Top">
                        <Path x:Name="DataTemplatePath" Height="16" Width="11" Fill="White"
                              Stretch="Fill" Margin="4,0,0,0" HorizontalAlignment="Center"
                              VerticalAlignment="Center" UseLayoutRounding="False"
                              Data="M337.59924,129.61948 L337.59924,141.51501 L345.5704,135.87381 z"/>
                    </Border>
                    <mpc:ListViewItem Layout="TextAndDetailsWithIcon" Text="{Binding Title}"
                                      Details="{Binding Body}" Style="{StaticResource PhoneListBoxItemLayout}"/>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</Grid>

I am only copying the main portion of UI, not entire page here.

I am also going to update the details page that is generated by the project wizard to match my data as well.  Here is what it looks like:

<Grid x:Name="LayoutRoot"
      Background="{StaticResource PhoneBackgroundBrush}"
      d:DataContext="{Binding Items[0]}">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <!--TitleGrid is the name of the application and page title-->
    <Grid x:Name="TitleGrid" Grid.Row="0">
        <Grid.Projection>
            <PlaneProjection/>
        </Grid.Projection>
        <TextBlock Text="{Binding Title}" Style="{StaticResource PhoneTextPageTitle2Style}"/>
    </Grid>
    <!--ContentGrid contains the details-->
    <Grid x:Name="ContentGrid" Grid.Row="1">
        <Grid.Projection>
            <PlaneProjection/>
        </Grid.Projection>
        <TextBlock TextWrapping="Wrap" Text="{Binding Body}"
                   Style="{StaticResource PhoneTextBodyTextStyle}"/>
    </Grid>
</Grid>

Now, let’s work on code behind to call our OData service.  Here is entire code behind for MainPage.xaml.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Phone.Controls;
using System.Windows.Navigation;
using EventModel;
using System.Collections.ObjectModel;
using System.Data.Services.Client;
using System.Windows.Input;
namespace WindowsPhoneListApplication1
{
    public partial class MainPage : PhoneApplicationPage
    {
        object _selectedItem;
        EventEntities _entities = new EventEntities(new Uri("http://api.visitmix.com/OData.svc/"));
        public MainPage()
        {
            InitializeComponent();
            SupportedOrientations = SupportedPageOrientation.Portrait;
            Loaded += new RoutedEventHandler(MainPage_Loaded);
            PageTransitionList.Completed += new EventHandler(PageTransitionList_Completed);
            var query = _entities.CreateQuery<Session>("Sessions");
            query.BeginExecute(ar =>
            {
                DataLoaded(ar);
            }, query);
        }
        private void DataLoaded(IAsyncResult result)
        {
            try
            {
                DataServiceQuery<Session> query = result.AsyncState as DataServiceQuery<Session>;
                List<Session> sessions = query.EndExecute(result).ToList();
                Dispatcher.BeginInvoke(() =>
                    {
                        this.ListBoxOne.ItemsSource = sessions;
                    });
            }
            catch (Exception ex)
            {
                Exception thing = ex;
            }
        }
        private void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            // Reset page transition
            ResetPageTransitionList.Begin();
        }
        private void ListBoxOne_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            // Capture selected item data
            _selectedItem = (sender as ListBox).SelectedItem;
            // Start page transition animation
            PageTransitionList.Begin();
        }
        private void PageTransitionList_Completed(object sender, EventArgs e)
        {
            // Set datacontext of details page to selected listbox item
            NavigationService.Navigate(new Uri("/DetailsPage.xaml", UriKind.Relative));
            FrameworkElement root = Application.Current.RootVisual as FrameworkElement;
            root.DataContext = _selectedItem;
        }
    }
}

The code above is fairly easy.  First, I create a DataSericeQuery of type Session.  Session type is part of our generated proxy.  It then call BeginExecute and pass it a handler.  Inside the handler (DataLoaded) I fire EndExecute, then set the items source for my ListBox.  I have to make sure to use Dispatcher for this call, otherwise I will get cross thread access exception because handler is not firing on UI thread.

That is it.  You can now run the application and see the list of sessions at the MIX 2010.  You can also click on an item to see the details.

Please post your questions here.

Thanks.

Post to Twitter

Getting Started with Windows Phone 7 and Silverlight

In this post I will go through the steps of creating my first Windows Phone 7 application using Silverlight.  It will be simple and will mostly concentrate on tools rather than phone specific functionality.  Of course, I will do more posts describing features that are specific to Silverlight for Windows Phone 7.

First thing I have to do is download the tools and install them on my machine.  You can find all appropriate link on www.Silverlight.net.  If you click on Getting Started menu, you can look for phone development tools.  You will download and install Visual Studio 2010 Express for Windows Phone.  Once you are done with that task, start the studio.

Here is what the screen look like.

image

Let’s go ahead and click on New Project link.  Let’s select Silverlight tree node, then Windows Phone application.  One side note – no VB.NET menu inside Studio for Phone.

image

Once project is created, you will see the screen that contains three parts by default – solution explorer, XAML view and Design view.

image

Now we can even run the application.  Let’s go ahead and do this.  What we will see is the Phone emulator as well as studio going to debug mode.  it will take a few minutes first time you run as emulator initializes.  You can resize the emulator by clicking on the menu that I have pointed to with a hand cursor on the picture below.  Eventually application loads, and you will the application just created, more precisely title and subtitle blocks.

image

Let’s add a few controls and some code now.  You will notice that when you stop debugging the studio that emulator keeps running.  This is good, and you want to keep it running in order to save deployment and initialization time. 

We will use the studio’s designer surface to add controls to the surface.  To do so, activate toolbox and pin it.

image

Let’s drag and drop a button onto design surface.  Here is what we will see now.

image

Let’s now add event handler for click event.  To do so, double-click on the button on design surface.  Code view will open and handler will be created.  We will do something really simple, we will change the title as follows:

 

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            this.textBlockPageTitle.Text = "I changed the title";
        }

Let’s run the application and see our code in action by clicking on the button.  Now, the step we are going to do is explore debugging.  To do so, set a breakpoint inside the event handler.

image

Run the application again from studio by clicking on debug button inside the studio.  I put hand cursor next the button.

image

Once the emulator loads the application, click on the new button inside the application we added.  Voila!  Our break    point got hit.

 

I illustrated in this post how to create a sample application inside Express Studio for Windows Phone, add controls to the design surface, write code behind and set breakpoints.

One last note.  You will notice that even new controls dropped onto design surface are styled certain ways to match overall phone design.  If you wonder why, it is because new project wizard comes preloaded with default styles for all basic controls.  To look at those styles, just open app.xaml.  For example, you can search for TargetType="ButtonBase" to see style for button.

There will be more to come as I explore phone specific features in Silverlight for Windows phone.

Thanks.

Post to Twitter

CodeStock Talk

I submitted sessions to this year’s CodeStock event.  You can vote now for all sessions here.

If you would like to see my session, please vote for them.  Here is my list

 

Thank you and I hope to see you there.

Post to Twitter

Getting Started with PowerPivot

Last week I took a stab at creating my first PowerPivot spreadsheet, and I wanted to document the steps.  Maybe this post will help someone, but it will help me remember, that is for sure!

Before you get started, you will need to download all the software required.  Here is my list:

Of course, you will need and instance of SQL Server 2008.  You can just use Express edition if you do not have one installed.

Now that I have everything installed and configured, I can start with PowerPivot.  One note – look for Hand shaped cursor in the screens below.s

Step 1 – Start up Excel 2010 and look for PowerPivot menu, then click on PowerPivot Window to launch pivot.

image

Step 2 – click on From Database in the window, then Select from SQL Server

image

Step 3 – Fill in SQL Server details.  I am choosing to use Data Warehouse DB.  Click Next when done.  On the next screen select an option to Select for a list of tables and views.

image

Step 4 – Select dimension tables and fact table to analyze.  Here is my list in alphabetical order

  • DimCustomer
  • DimDate
  • DimProductCategory
  • DimSalesTerritory
  • FactInternetSales

You can select any tables you like of course.  Wait while data is imported into PowerPivot, then click Close.  PowerPivot window will now have five tabs with data and columns directly imported from the database.  Here is what it looks like.

image

Now click on PivotTable menu and select  Chart and Table – Vertical option.  We will simply create a chart and an analysis table to go with it.  Click on New Worksheet when prompted.  This step will return you back to main Excel window.  You will see chart, table and on the left hand side Gemini task pane – listing of imported data.  Gemini used to be Microsoft code name for this product/functionality.

image

Step 5 – Building a chart.  We are going to analyze sales based on customer marital status by linking it to sales amount.  Click on the chart first, then in Gemini pane expand DimCustomer table and select MaritalStatus.  Then, expand FactInternetSales and select SalesAmount.  PowerPivot will guess what we are trying to do and MaritalStatus as Axis field and Sum(SalesAmount) as Values.  Here is what it looks like:

image

 

Step 6 – building table with filters. 

Click on table first, then check the following tables/fields in Gemini pane:

  • DimCustomer – MaritalStatus and Gender
  • DimDte – CalendarYear
  • DimProductCategory – EnglishProductCategoryName
  • DimSalesTerritory – SalesTerritoryCountry
  • FactInternetSales – SalesAmount

At this point your bottom of Gemini pane should look like this:

image

if you have anything else in Values, click on that item and select “Move to Row labels”.  What you will see also is that your have a report built for you in table area that uses all the analysis points.  You could leave it as is, but I will do more.

 

Step 7 Now I can analyze the data by “slicing it”.  To do this we will create two groups of slices – horizontal and vertical.  We will split our analysis categories as follows:

  • Horizontal Slices: Marital Status and Gender
  • Vertical Slices –English Product Category and Calendar Year.

I will leave Sales Territory country as a column in my table. To perform this I will click on each of my slices and select “Move to Slices Horizontal (or Vertical) as appropriate.  Then I click on each slice and choose Move Up or down until my pane looks like this:

image

Now here is what my table looks:

image

I will go ahead and move things around to make spreadsheet look better:

image

 

Step 8 – Use slices for analysis.  This process is super simple – just click on a desired slice(s) to enact filter on rows of a table.

image

To clear the filter just click on a funnel picture with x across it:

image

As you do so, you will see the chart and table both updating with your filter values.  One thing I did notice at the end – Catergory is lon linked to internet sales, so category filter has no effect on data.  If you see similar behavior, your data has the same issue.  You can always manually build relationships in PowerPivot by click on Table tab in pivot and choosing Manage Relationships menu:

image

 

As you can see, using PowerPivot is extremely easy and the results are very powerful.  You can save your spreadsheet, open it later and refresh the data by clicking on a filter!  You also have an option to show or hide Gemini panels in Excel under PowerPivot menu.  In the same menu you also have an option to show or hide Gemini panels.

Thanks.

Post to Twitter

Extending Interfaces with Implementation

Today I was faced with an issue.  I had an interface based implementation of a specific functionality.  All classes that implemented this interface had different implementation of course.  What I had to add is ability to run certain checks on each implementation that would need to analyze the data defined in the interface and return a Boolean result of this check.

The problem was that the checks were all the same and I hated to add this check to the interface and write identical code in all implementations.  As everyone knows interfaces cannot contain implementation code though.  So, what should I do?

So, a particular .NET 3.5 feature came to my rescue.  I am referring to extension methods.  As you may or may not know extension methods are tied to a type.  Well, interface is a type too.  Here is some code to look at.

Here is the interface definition:

    public interface ISupportCustomAction

    {

        Action CustomAction { get; set; }

        void Execute();

    }

Here is my class definition that implements this interface

    public class CustomActionOne : ISupportCustomAction

    {

        #region ISupportCustomAction Members

        private Action action;

        public Action CustomAction

        {

            get

            {

                return action;

            }

            set

            {

                action = value;

            }

        }

 

        public void Execute()

        {

            // fill in the method

        }

 

 

        #endregion

    }

Finally, here is my extension method

    public static class ISupportCustomActionExtensions

    {

        public static bool Check(this ISupportCustomAction action)

        {

            if (action.CustomAction == null)

            {

                return false;

            }

            else

            {

                return true;

            }

        }

    }

Here is my test code to confirm that everything works

    class Program

    {

        static void Main(string[] args)

        {

            CustomActionOne action = new CustomActionOne();

            action.CustomAction = () => { Debug.WriteLine("Exectuted Action."); };

            Analize(action);

 

            action = new CustomActionOne();

            Analize(action);

            Console.ReadKey();

        }

 

        private static void Analize(ISupportCustomAction action)

        {

            if (action.Check())

            {

                Console.WriteLine("Can execute action");

            }

            else

            {

                Console.WriteLine("Cannot execute action");

            }

        }

    }

How useful this is?  Pretty useful in my case.  Saved me some typing and resulted in consistent coding.  My point is that is good to know what features .NET has and use them as a need arises.  As you can see I have a hybrid here of a base (abstract) class and an interface.  As a result, I am able to use features that belong to both concepts.

What does this code remind you of?  Can you say “Multiple Inheritance in C#?”  Well, not exactly, but pretty close.

 

Thanks.

Post to Twitter

Community Events

I often forget about different conferences I would like to keep an eye on, so I decided to make a list of them on my blog.

Post to Twitter

Silverlight 4 + COM + SQL Server = Cool!

Today is the day to talk about COM possibilities in Silverlight 4.  One would question the titles of my post.  COM and Cool in the same sentence?  Let me proof this title to you.

First, let me take a closer look at COM.  In order to access COM, you must install Silverlight application on a local machine.  The access to COM is not enabled when a Silverlight application is run in the browser.  So, first of all you have to enable this by checking “Enable running application out of browser” checkbox in project properties.  Second of all, you have to check “Require elevated trust…” checkbox in “Out-of-browser settings” area in project properties.  Now, you are ready to install you application and test COM support.  How about Word automation:

Microsoft.Office.Interop.Word.Application word = new Microsoft.Office.Interop.Word.Application();
var doc = word.Documents.Add();
var paragraph = doc.Paragraphs.Add();
paragraph.Range.Text = "Some text";

Now, let’s talk about database access.  Parts of System.Data.SqlClient namespace are not exposed to COM by default.  So, to enable database access we must write an assembly that is exposed to COM that wraps database access.  To do so, check the property “Register for COM Interop” in project properties for the .NET (NOT Silverlight) based project that will fire off database queries for us.  Once the assembly is built, I can just use RegAsm to register my DLL with COM on a machine.  Of course, this would be a prerequisite to use Silverlight application for local data access.  The other prerequisite is to have .NET Runtime installed on that machine as well.  I could write an install project of course to make this process easier.

The next step is to write a Silverlight assembly that would use COM Interop similar to the one above for Word to talk to my database access .NET based assembly.

dynamic sqlDB = ComAutomationFactory.CreateObject("COMSQLClient.COMSqlDatabase");

Now the most exciting part.  I created and published the project on CodePlex that does exactly what I just talked about.  Check out the project and let me know what you think.  You can download the source code and look into the implementation details.  Here is the link to it:

http://silverlight4sqllib.codeplex.com/

Thanks.

Post to Twitter

The MSDN Southern Fried Roadshow

Glen Gordon, our local evangelist is doing another road show.  Here are the event details.

Thursday, February 25, 2010 1:00 PM – Thursday, February 25, 2010 5:00 PM Eastern Time (US & Canada)
Welcome Time: 12:30 PM

Atlanta Marriot Alpharetta

5750 Windward Pkwy
Alpharetta Georgia 30005
United States

Language(s):
English.

Product(s):
Azure Services Platform, Microsoft technologies, Windows and Windows 7.

Audience(s):
Pro Dev/Programmer.

Presenter(s):
Glen Gordon, Joe Healy

Event Overview

MSDN Events presents: Take Your Applications Sky High with Cloud Computing and the Windows Azure Platform

Join your local MSDN Events team as we take a deep dive into cloud computing and the Windows Azure Platform. We’ll start with a developer-focused overview of this new platform and the cloud computing services that can be used either together or independently to build highly scalable applications. As the day unfolds, we’ll explore data storage, SQL Azure, and the basics of deployment with Windows Azure. Register today for these free, live sessions in your local area.

If you register and attend this event, you will be placed in a raffle to win a chance to bring home one (1) free copy of Windows 7 – you could be the lucky winner! Register today!

SESSION 1: Overview of Cloud Computing and Windows Azure

The Windows Azure platform is a set of high-performance cloud computing services that can be used together or independently and enable developers to leverage existing skills and familiar tools to develop cloud applications. In this session, we’ll provide a developer-focused overview of this new online service computing platform. We’ll explore the components, key features and real day-to-day benefits of Windows Azure.

Highlights include:

· What is cloud computing?

· Running web and web service applications in the cloud

· Using the Windows Azure and local developer cloud fabric

· Getting started – tools, SDKs and accounts

· Writing applications for Windows Azure

SESSION 2: Survey of Windows Azure Platform Storage Options

Durable data storage is a key component of any cloud computing offering. The Windows Azure Platform offers many options, which can be used alone or in combination. Windows Azure itself offers ready-to-use and lightweight storage in the form of tables, blobs, and queues. Another choice for storage is SQL Azure, a true relational database in the cloud. In this session, we’ll explore the highlights of these implementations and how to both create and use storage in each form. We’ll give you guidance on choosing the right forms of storage for your application scenarios.

Highlights include:

· Understanding table & blob storage

· Programming against table & blob storage

· Working with queue storage

· Managing credentials and connection strings

· Scaling and configuration

· Understanding SQL Azure databases versus local SQL Server databases

· SQL Azure firewall, logins and passwords

· Database creation, deployments and migrations

· Database management using SQL Management Studio

· Programming against SQL Azure databases

SESSION 3: Going Live with your Azure Solution

Windows Azure features a powerful, yet simple deployment model. By focusing on your application and abstracting away the infrastructure details, you can deploy almost any app with minimal fuss. In this session, we’ll walk you through the basics of Windows Azure deployment, including site monitoring, diagnostics and performance issues.

Highlights include:

· Start-to-Finish Visual Studio demonstration of a realistic XML data driven business web site from the desktop to the cloud.

· Windows Azure Deployments

· Start-to-Finish Visual Studio demonstration of a realistic SQL Server data driven business web site from the desktop to the cloud.

· Configuration of your application in the cloud

· Guidance and Suggestions to ensure your success

*Be sure to learn more about the TechNet event happening on the same day at the same location from 8:30am–12:00pm. If you are interested in attending, please register separately for that event here: http://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032439495&Culture=en-US

Registration Options

Event ID:
1032439974

Here is the link to this event:

http://msevents.microsoft.com/CUI/EventDetail.aspx?EventID=1032439974&Culture=en-US

Post to Twitter

Entity Framework 4.0 and Multiple Data Contexts

In the EF version 1.0, there was a problem when one would try to update multiple contexts as part of a single transaction.  For example, I can use Transaction Scope, the update one context, then second context.  Here is sample code to illustrate:

 

using (TransactionScope scope = new TransactionScope())
{
    try
    {
        using (RolodexEntities context = new RolodexEntities())
        {
            context.Connection.Open();

            Company company = new Company();
            company.CompanyName = "Test 1";
            company.DateAdded = DateTime.Today;
            context.AddToCompanies(company);
            context.SaveChanges();

            using (RolodexEntities context2 = new RolodexEntities(context.Connection as EntityConnection))
            {
                Company company2 = new Company();
                company2.CompanyName = "Test 1";
                company2.DateAdded = DateTime.Today;
                context2.AddToCompanies(company2);
                context2.SaveChanges();
            }
        }

        scope.Complete();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

This code in version 1.0 would throw an exception when second context’s constructor was called.  The exception was quite obscure and was referring to the fact that the connection was already open.  This was actually correct, but that was the whole reason I was passing in the connection.  I was trying to make sure that my transaction would not get promoted to Distributed Transactions Coordinator.  The transaction would always get promoted as soon as there are multiple SQL Server connections used within using scope/.end using scope code block.  So, in version 1.0 MSDTC would be required in the code above.

This issue still exists in EF 4.0.  You can vote to fix the issue here : https://connect.microsoft.com/data/feedback/details/533240/cannot-share-a-store-connection-between-multiple-contexts-in-order-to-avoid-dtc-promotion

Here is the code that confirms the problem:

using (TransactionScope scope = new TransactionScope())
{
    try
    {
        using (RolodexEntities context = new RolodexEntities())
        {
            context.Connection.Open();

            Company company = new Company();
            company.CompanyName = "Test 11";
            company.DateAdded = DateTime.Today;
            context.AddToCompanies(company);
            context.SaveChanges();

            RolodexEntities1 contextTemp = new RolodexEntities1();
            MetadataWorkspace space = (contextTemp.Connection as EntityConnection).GetMetadataWorkspace();
            EntityConnection connection = new EntityConnection(space, (context.Connection as EntityConnection).StoreConnection);

            using (RolodexEntities1 context2 = new RolodexEntities1(connection))
            {
                User user = new User();
                user.UserName = "test";
                user.Role = "User";
                context2.AddToUsers(user);
                context2.SaveChanges();
            }
        }

        scope.Complete();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

Please feel free to ask any questions on this subject.

Post to Twitter

Silverlight, MVVM and Animations

Yesterday I was asked about a way to play animations in MVVM environment.

So, I gave this some thought today, and came up with a few ideas.

First, and the easiest way is to separate ViewModel from animation by attaching an animation to a behavior.  Here is how we would write the behavior:

public class MVVMSimpleAnimationBehavior : TargetedTriggerAction<UIElement>

{

    protected override void Invoke(object parameter)

    {

        RunAnimation();

    }

 

    public Storyboard AnimationStoryBoard

    {

        get { return (Storyboard)GetValue(AnimationStoryBoardProperty); }

        set { SetValue(AnimationStoryBoardProperty, value); }

    }

 

    public static readonly DependencyProperty AnimationStoryBoardProperty =

        DependencyProperty.Register("AnimationStoryBoard", typeof(Storyboard), typeof(MVVMSimpleAnimationBehavior), new PropertyMetadata(null));

 

 

    private void RunAnimation()

    {

        if (AnimationStoryBoard != null)

        {

            AnimationStoryBoard.Begin();

        }

    }

}

 

Pretty simple approach.  Here is how would use animation in the XAML:

<Button Content="Behavior Test" Grid.Column="1">

    <i:Interaction.Triggers>

        <i:EventTrigger EventName="Click">

            <local:MVVMAnimationBehavior AnimationStoryBoard="{StaticResource TestStoryboard}"/>

        </i:EventTrigger>

    </i:Interaction.Triggers>

</Button>

Now, I want to complicate the story a little bit.  I really want to trigger an animation in the UI via an event in my model.  I am going to start with a sample ViewModel.  I want to have an event there that I will later use as a trigger for my animation.  Here is what my ViewModel would look like:

public class SampleModel: INotifyPropertyChanged

{

 

    public event EventHandler StartAnimation;

 

    protected virtual void OnStartAnimation()

    {

        if (StartAnimation != null)

        {

            StartAnimation(this, EventArgs.Empty);

        }

    }

 

    public void RaiseEvent()

    {

        OnStartAnimation();

    }

 

    #region INotifyPropertyChanged Members

 

    public event PropertyChangedEventHandler PropertyChanged;

 

    protected virtual void OnPropertyChanged(string propertyName)

    {

        if (PropertyChanged != null)

        {

            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

        }

    }

 

    #endregion

}

My event is called StartAnimation.  Now it is time to develop a more complicate behavior to support my event driven animation from ViewModel.  I am going to actually combine new functionality with the simple behavior about and have multi-functional useful object.  Here is what the final product looks like:

using System;

using System.Windows.Interactivity;

using System.Windows;

using System.Windows.Media.Animation;

using System.ComponentModel;

using System.Reflection;

 

 

namespace SLMVVMAnimationBehavior

{

    public class MVVMAnimationBehavior : TargetedTriggerAction<UIElement>

    {

        private EventInfo info;

        protected override void Invoke(object parameter)

        {

            RunAnimation(this, EventArgs.Empty);

        }

 

        public Storyboard AnimationStoryBoard

        {

            get { return (Storyboard)GetValue(AnimationStoryBoardProperty); }

            set { SetValue(AnimationStoryBoardProperty, value); }

        }

 

        public static readonly DependencyProperty AnimationStoryBoardProperty =

            DependencyProperty.Register("AnimationStoryBoard", typeof(Storyboard), typeof(MVVMAnimationBehavior), new PropertyMetadata(null));

 

        public string EventName

        {

            get { return (string)GetValue(EventNameProperty); }

            set { SetValue(EventNameProperty, value); }

        }

 

        public static readonly DependencyProperty EventNameProperty =

            DependencyProperty.Register("EventName", typeof(string), typeof(MVVMAnimationBehavior), new PropertyMetadata(HandlModelChanged));

 

 

        public object Model

        {

            get { return GetValue(ModelProperty); }

            set { SetValue(ModelProperty, value); }

        }

 

        public static readonly DependencyProperty ModelProperty =

            DependencyProperty.Register("Model", typeof(object), typeof(MVVMAnimationBehavior), new PropertyMetadata(HandlModelChanged));

 

        private static void HandlModelChanged(object sender, DependencyPropertyChangedEventArgs e)

        {

            MVVMAnimationBehavior behavior = sender as MVVMAnimationBehavior;

            object model = behavior.Model;

            if (behavior.info != null)

            {

                behavior.info.RemoveEventHandler(model, Delegate.CreateDelegate(typeof(EventHandler), behavior, "RunAnimation"));

            }

            if (model != null && !string.IsNullOrEmpty(behavior.EventName))

            {

                behavior.info = model.GetType().GetEvent(behavior.EventName);

                behavior.info.AddEventHandler(model, Delegate.CreateDelegate(typeof(EventHandler), behavior, "RunAnimation"));

 

            }

        }

 

        private void RunAnimation(object sender, EventArgs e)

        {

            if (AnimationStoryBoard != null)

            {

                AnimationStoryBoard.Begin();

            }

        }

    }

}

 

 

As you can see, I added two mode dependency properties – one for event name that will trigger the animation, the other one for ViewModel ( I actually called it model).  Now the tricky part is to use a bit of reflection to attach an event handler to the event on my model.  This is done in HandlModelChanged routine that is called when Model or Event name is set.  I am getting an event, and attaching a handler to it.  The actual handler is located inside the behavior itself – RunAnimation method.  Here is what my fianl XAML looks like that is testing both animation approaches:

<UserControl x:Class="SLMVVMAnimationBehavior.MainPage"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

    xmlns:local="clr-namespace:SLMVVMAnimationBehavior"

    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">

    <UserControl.Resources>

        <Storyboard x:Name="TestStoryboard">

            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="textBlock" Storyboard.TargetProperty="(TextBlock.FontSize)">

                <EasingDoubleKeyFrame KeyTime="00:00:00.1000000" Value="24"/>

                <EasingDoubleKeyFrame KeyTime="00:00:00.2000000" Value="21.333"/>

                <EasingDoubleKeyFrame KeyTime="00:00:00.3000000" Value="18.667"/>

                <EasingDoubleKeyFrame KeyTime="00:00:00.4000000" Value="16"/>

                <EasingDoubleKeyFrame KeyTime="00:00:00.5000000" Value="13.333"/>

                <EasingDoubleKeyFrame KeyTime="00:00:00.6000000" Value="16"/>

                <EasingDoubleKeyFrame KeyTime="00:00:00.7000000" Value="18.667"/>

                <EasingDoubleKeyFrame KeyTime="00:00:00.8000000" Value="21.333"/>

                <EasingDoubleKeyFrame KeyTime="00:00:00.9000000" Value="24"/>

                <EasingDoubleKeyFrame KeyTime="00:00:01" Value="26.667"/>

            </DoubleAnimationUsingKeyFrames>

        </Storyboard>

        <local:SampleModel x:Key="CurrentModel" />

        <local:MVVMAnimationBehavior AnimationStoryBoard="{StaticResource TestStoryboard}" Model="{StaticResource CurrentModel}" x:Key="Animation" EventName="StartAnimation"/>

    </UserControl.Resources>

    <Grid x:Name="LayoutRoot" Background="#FFF3EEEE" DataContext="{Binding Source={StaticResource CurrentModel}}">

        <Grid>

            <Grid.ColumnDefinitions>

                <ColumnDefinition Width="Auto"/>

                <ColumnDefinition Width="Auto"/>

                <ColumnDefinition/>

            </Grid.ColumnDefinitions>

            <Grid.RowDefinitions>

                <RowDefinition Height="Auto"/>

                <RowDefinition/>

            </Grid.RowDefinitions>

            <Button x:Name="TestButton" Content="Click To Start Animation" d:LayoutOverrides="Height" HorizontalAlignment="Left" Click="TestButton_Click"/>

            <Button Content="Behavior Test" Grid.Column="1">

                <i:Interaction.Triggers>

                    <i:EventTrigger EventName="Click">

                        <local:MVVMAnimationBehavior AnimationStoryBoard="{StaticResource TestStoryboard}"/>

                    </i:EventTrigger>

                </i:Interaction.Triggers>

            </Button>

            <TextBlock x:Name="textBlock" Margin="0,0,0,6" Text="Sample Text" TextWrapping="Wrap" d:LayoutOverrides="Width, Height" Grid.Row="1" Grid.ColumnSpan="3" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="26.667"/>

        </Grid>

 

    </Grid>

</UserControl>

 

To summarize, I illustrate a couple of approaches to trigger animations in MVVM environment.  Of course, there is always code-behind, but many developers frown at this approach..

Please let me know if you have any questions.

Post to Twitter

WCF RIA Services Validation

Today I am continuing exploring WCF RIA Services.  I am going to discuss validation in RIA Services.

Any business application needs to validate user input.  I am going to start with a simple case.  In my sample application a user can enter a company information.  I would like to setup RIA Services to force the user to enter a company name before he or she can save the company.  In order to do so I am going to use Data Annotations.  First of all, I need to add a reference to System.ComponentModel.DataAnnotations DLL to all my projects.  RIA Services project should already have the reference. 

Now I need to edit my metadata file that corresponds to my data model under .NET version of RIA Services.  In my case it is RolodexDomainService.metadata.cs file in SilverlightRIAServicesLibrary.Web project.  In that file I need to find Companies class, then location company name property, then decorate the property with required attribute.  At the same time we will also put a limit on how many characters a user can enter:

[Required]

[StringLength(30)]

public string CompanyName;

 

If we want to see the results of our changes, we can run the application, then clear company name for an existing comp-any, then tab out of company name field.  Here we get visual feedback that our input was not valid:

image

Now, let’s create custom validation.  Fir example, I am going to force the date added to be no less that 1/1/2000.  To do this I will write a custom validation class like so:

public static class ValidationHelper

{

    public static ValidationResult DateAddedCheck(DateTime date)

    {

        ValidationResult result;

        if (date > new DateTime(2000, 1, 1))

        {

            result = new ValidationResult("");

        }

        else

        {

            result = new ValidationResult("Date is not valid");

        }

 

        return result;

    }

}

Validation method that I wrote is a static member.  It follows a specific signature that RIA Services requires.  For example, it returns Validation Result that contains specific information that validation infrastructure of RIA Services can parse.  Overall code is fairly simple.

In order to make this class available on the Silverlight side, I must include my validation class into Silverlight version of RIA Services library – SilverlightRIAServicesLibrary project in my case.  In order not to duplicate the code, I will include the same class as a link.  I right-click on the project, choose add existing item, navigate to my class, then click on down arrow on Add button, and select Add As Link.  Now I have the same validation on both .NET and Silverlight side.  To confirm, I just build and run the application.  Here is what my DateAdded attributes look like:

[Required]

[CustomValidation(typeof(ValidationHelper), "DateAddedCheck", ErrorMessage = "Date is not valid")]

public DateTime DateAdded;

On important thing to mention that in  order to see validation error in UI, we need to update our Binding to look as following:

<TextBox x:Name="CompanyNameTextbox" Grid.Column="1" Grid.Row="0" HorizontalAlignment="Stretch" Margin="6,6,6,6" Text="{Binding Path=CompanyName, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnExceptions=True}" VerticalAlignment="Center"/>

There is one important thing to notice.  If you look at Silverlight side generated code, you will notice that validation occurs before the property value is set.  As a result, you cannot rely on property value being set if a validation exception is thrown.

Now, let’s look at saving code that we had to modify in order to validate user input.  Here is what it looks like:

try

{

    Validator.ValidateObject(this.Model, new ValidationContext(this.Model, null, null), true);

    if (this.Model.HasChanges)

    {

        ShowPleaseWaitMessage();

        _context.SubmitChanges(HandleSave, null);

    }

}

catch (ValidationException ex)

{

    MessageBox.Show(ex.Message);

}

Not really the cleanest code because we have to rely on exceptions being thrown. 

I covered all key area of validation, but there is more for you to explore.  Please let me know if you have any questions.

Post to Twitter

Windows Azure

I just want to relay Microsoft’s new offer to everyone.  Windows Azure is now offered for free for a limited time.  This is an introductory offer to get more people to use new cloud platform from Microsoft.  Please see this link for details.

Post to Twitter

Speaking at Atlanta .NET Users Group

I spoke at Atlanta.NET Users Group yesterday, My topic was Azure Step-by-Step.

I talked about why someone would use Windows and SQL Azure, then I built a Silverlight application from scratch.  The application was designed to run in Windows Azure and use SQL Azure as database.  I demonstrated how to get maximum code re-use between traditional .NET web application and the same application developed for Azure.  At the end, I had an application that could run on either platform with just web.config change.

You can download the zip file with PowerPoint slides with useful links as well as the sample project I built here.

Please let me know if you have any questions.

Post to Twitter

RIA Services (Cont.)

In this post I will cover the update process.

I am going to recap where I left off in the last post on RIA Services.  The last step was to retrieved based on ID from a read only company object.  Once this object is obtained in the VIewModel, we can create a screen to edit a company.

Here is how I am getting the company by ID in the ViewModel class:

var

companyQuery = _context.GetCompanyQuery(_companyID);

 

_context.Load<Companies>(companyQuery, (o1) =>

 

{

 

    HidePleaseWaitMessage();

 

    if (o.Error != null)

 

    {

 

        ErrorHandler.HandleException(o.Error);

 

    }

 

    else

 

    {

 

        this.Model = o1.Entities.First() as Companies;

 

    }

 

}, null);

Now that I have my Model property set, I can create a user control to edit the company.  Here is the part of the XAML for the edit form that shows the binding:

<UserControl x:Class

=”Rolodex.Silverlight.Views.CompanyEditView”

 

    xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”

 

    xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”

 

    xmlns:controls=”clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data”

 

    xmlns:input=”clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls”

 

    xmlns:cal=”clr-namespace:Microsoft.Practices.Composite.Presentation.Commands;assembly=Microsoft.Practices.Composite.Presentation”

 

    xmlns:core=”clr-namespace:Rolodex.Silverlight.Core”

 

    >

 

    <UserControl.Resources

>

 

       

 

    </UserControl.Resources

>

 

    <Grid x:Name

=”LayoutRoot”>

 

        <Grid.RowDefinitions

>

 

            <RowDefinition Height

=”*”/>

 

            <RowDefinition Height

=”Auto”/>

 

        </Grid.RowDefinitions

>

 

        <Grid x:Name=”EditGrid” DataContext=”{Binding Model

}”>

 

            <Grid.RowDefinitions

>

 

                <RowDefinition Height

=”35″/>

 

                <RowDefinition Height

=”35″/>

 

                <RowDefinition Height

=”1*”/>

 

                <RowDefinition Height

=”35″/>

 

                <RowDefinition Height

=”1*”/>

 

                <RowDefinition Height

=”35″/>

 

            </Grid.RowDefinitions

>

 

            <Grid.ColumnDefinitions

>

 

                <ColumnDefinition Width

=”Auto”/>

 

                <ColumnDefinition Width

=”200″/>

 

                <ColumnDefinition Width

=”*”/>

 

            </Grid.ColumnDefinitions

>

 

            <TextBlock Text=”Company Name:” TextAlignment=”Right” HorizontalAlignment=”Right” Grid.Column=”0″ Grid.Row=”0″ Margin=”6,6,6,6″ VerticalAlignment

=”Center”/>

 

            <TextBox x:Name=”CompanyNameTextbox” Grid.Column=”1″ Grid.Row=”0″ HorizontalAlignment=”Stretch” Margin=”6,6,6,6″ Text=”{Binding Path=CompanyName, Mode=TwoWay}” VerticalAlignment

=”Center”/>

 

            <TextBlock Text=”Date Added:” TextAlignment=”Right” HorizontalAlignment=”Right” Grid.Column=”0″ Grid.Row=”1″ Margin=”6,6,6,6″ VerticalAlignment

=”Center”/>

 

            <input:DatePicker x:Name=”DateAddedTextbox” SelectedDate=”{Binding DateAdded, Mode=TwoWay}” Grid.Column=”1″ Grid.Row=”1″ HorizontalAlignment=”Stretch” Margin=”6,6,6,6″ VerticalAlignment=”Center”/>

So far, I have an instance of a Companies object that is bound to the data context of my user control.  At this point a user can edit company name and date added fields.  Logically, the next thing a user would want to do is to save his changed – the nerve of him :-)

So, let’s take a look at the Save command in our view model object.

 

protected

override void BeginSave()

 

{

 

    ShowPleaseWaitMessage();

 

    _context.SubmitChanges(HandleSave, null);

 

}

 

 

 

private

void HandleSave(SubmitOperation operation)

 

{

 

    HidePleaseWaitMessage();

 

    if (operation.Error != null)

 

    {

 

        ErrorHandler.HandleException(operation.Error);

 

    }

 

}

Save is a two step process because all communication in Silverlight is asynchronous.  We are starting the save process in BeginSave, and we are checking for errors in HandleSave methods respectively.  The key part to this process is client side context of RIA Services that keeps track of all the changes that the user is making after the object has been initially retrieved via a call to the server.  The key work is done by the domain service object – LinqToEntitiesDomainService<RolodexEntities> in our case.  We can look at this code generated by the RIA Services wizard by looking at RolodexDomainService.cs class in my case.  There is a bug in current CTP that causes update to parent and child objects not being flushed properly.  In my case I have Companies object that contains a list of ComanyContacts objects.  Generated code has check for EntityState in UpdateCompanyContacts method that I had to remove to get the process to work.  Here is the final version of key methods of the Domain service class:

public

void UpdateCompanies(Companies currentCompanies)

 

{

 

    this.ObjectContext.AttachAsModified(currentCompanies, this.ChangeSet.GetOriginal(currentCompanies));

 

}

public

void UpdateCompanyContacts(CompanyContacts currentCompanyContacts)

 

{

 

    this.ObjectContext.AttachAsModified(currentCompanyContacts, this.ChangeSet.GetOriginal(currentCompanyContacts));

 

}

So, after this step all parts of the process are working – I can update companies and contacts.

Please email me any questions,

Post to Twitter

Velocity Presentation

As I mentioned previously, I presented on the topic of Velocity at the Atlanta Leading Edge Microsoft Users Group on Tuesday, January 19th.

The talk went pretty well, we had a lot of technical questions.  I really enjoyed this presentation, as I am always excited to speak on a new topic that I have not covered previously. 

You can download materials here.

 

Please let me know if you have any questions.

Post to Twitter

RIA Services (Cont.)

I am going to continue exploring the topic of RIA services and Silverlight.  I thought I was going to get into updates in this post, but there are a few topics I would like to cover first.  I am going to try to get to updates in the next post.

Today, I am going to explore two more topics.  I am going to cover extending RIA Services DomainContext with custom classes and working on including child objects when fetching a parent object using Entity Framework and RIA Services.

 

First, I am going to extend my DomainContext with a custom class.  In my case I have Company Object/Table with a number of columns.  In my Silverlight application I would like to have a list of companies that shows only company name.  When a user selected one company, I would like to fetch full company object with company contacts child object.  If I were to use the method that the wizard built for me – public IQueryable<Companies> GetCompanies(),I would get the full object with all columns.  So, I am going to build a custom class that only has company ID and name:

    public class ReadOnlyCompany

    {

        [Key]

        public int CompanyId { internal set; get; }

        public string CompanyName { internal set; get; }

    }

 

I am going to add this class to RIA Service project on .NET side (SilverlightRIAServicesLibrary.Web project in my case).  As you notice I did not have to decorate my class with DataContract attribute or decorate properties with DataMember attribute.  We do not actually need to do this, as RIA Services will take care of all that for us.  I do however need to use Key attribute or I would get a compile time error.  Each object is required to have a key (primary key) property.  Next step is to write a method in DomainService (RoldexDomainService in my case) class.  Here is what this would look like:

        public List<ReadOnlyCompany> GetReadOnlyCompanies()

        {

            return (from oneCompany in this.ObjectContext.Companies

                    orderby oneCompany.CompanyName

                    select new ReadOnlyCompany()

                    {

                        CompanyId = oneCompany.CompanyId,

                        CompanyName = oneCompany.CompanyName

                    }).ToList<ReadOnlyCompany>();

        }

 

Even though I return List object here, but RIA Services will actually return ReadOnlyObservableCollection<ReadOnlyCompany> on Silverlight side.  You have to remember that when you cast return value for RIA Services call to a specific object.  Here is what this call would look like on Silverlight side:

        private void GetCompaniesList()

        {

            ShowPleaseWaitMessage();

            var query = _context.GetReadOnlyCompaniesQuery();

 

            _context.Load<ReadOnlyCompany>(query, LoadBehavior.RefreshCurrent, (o) =>

            {

                HidePleaseWaitMessage();

                if (o.Error != null)

                    ErrorHandler.HandleException(o.Error);

                else

                {

                    this.Model = o.Entities as ReadOnlyObservableCollection<ReadOnlyCompany>;

                }

                    HidePleaseWaitMessage();

            }, null); ;

 

        }

Here I am putting up a please wait window, fire a query and interpret the results.  As I mention before, my next step is to get full Company object based on selected ID.  Again, I am adding a new method to DomainService class on .NET side:

        public Companies GetCompany(int companyID)

        {

            var returnValue = this.ObjectContext.Companies

                .Include("CompanyContacts")

                .Include("CompanyContacts.CompanyContactPhones")

                .Where(one => one.CompanyId == companyID).FirstOrDefault();

            return returnValue;

        }

Now, let’s see what this call looks like on Silverlight side.  This also demonstrates the use of parameters:

var companyQuery = _context.GetCompanyQuery(_companyID);

_context.Load<Companies>(companyQuery, (o1) =>

{

    HidePleaseWaitMessage();

    if (o.Error != null)

    {

        ErrorHandler.HandleException(o.Error);

    }

    else

    {

        this.Model = o1.Entities.First() as Companies;

    }

}, null);

As you can see, RIA services build us a query that already has the same company ID parameter for us.  Pretty cool!  However, if I look at return value (Companies object), I will notice that contacts property is actually null even though I did add .Include statement to my custom Entity Framework based method.  To get this to work, I have to modify the metadata class that RIA Services generated(RolodexDomainService.metadata.cs in my case).  I need to open this class file and look for Companies object.  I will find public EntityCollection<CompanyContactPhones> CompanyContactPhones property in it.  To get RIA Services to include child collection, I need to add Include attribute here as well:

[Include]

public EntityCollection<CompanyContactPhones> CompanyContactPhones;

I would have to take the same step to include phones collection for each contact.  If I run my code again, I will not get Company object with a list of Contacts, each containing a list of Phones.

I will try to cover update in my next post.

Thank you and do not hesitate to ask questions.

Post to Twitter

Talk at GGMUG

As always I had fun presenting at Gwinnett Georgia Microsoft Users Group on Thursday.  The subject of my talk was “Getting started with SQL Azure”.  I documented all the steps in this blog post.  There are also useful links that I mentioned in this post to help you get started.

There are many advantages to use SQL Azure.  Number of reason is probably the fact that one can eliminate the need to house expensive hardware and software on premises.  As long as you are fine with living with certain limitations of SQL Azure compared to SQL Server 2008, you can take advantage of this great technology.  The primary limitation is probably the size of the database.  You cannot have a database bigger than 10 GB.

Feel free to ask any questions on the topic.

Post to Twitter

Microsoft MVP

I have just been selected to receive the Microsoft MVP award!  This is an awesome news!  I feel honored and humbled that Microsoft recognized my efforts in learning Microsoft technologies and being active in local Microsoft oriented developer communities, user groups and events.  At the risk of making cliché comments, I would like to recognize a few people and organizations that encouraged me to strive to do my best.

As much as I learned by working at Horizon Software, there is no way I would have gotten where I am without Magenic Technologies.  This the most awesome company to work for.  Great environment and great people too numerous to mention encouraged me to work hard every day.  Participating in local users group has been invaluable experience for me as well.  I have met many people smarter than me over the last number of years that helped me out a lot.  Special thanks to Glen Gordon, local Microsoft developer evangelist for nominating me.  I am very much looking forward to many exciting years learning and (hopefully) teaching Microsoft technologies.

Post to Twitter

Getting Started with WCF RIA Services

I know many posts have been written on this subject by many people, but I am writing this one mostly for myself.  I find it very useful to type my thoughts on any subject and create a sample project to help me commit more information to memory.  So, here it goes.

What you need to get started.

  1. Visual Studio 2008 SP 1 (You can use 2010 as well)
  2. WCF RIA Services Beta for Visual Studio 2008 SP1 (http://www.microsoft.com/downloads/details.aspx?FamilyID=76bb3a07-3846-4564-b0c3-27972bcaabce&displaylang=en)

Here is what needs to be done next.

Create new Silverlight project.  To do so just create new project and select Silverlight.  Make sure to create a host web site as well.

image

On the next wizard screen select an option to create new host web site and enable .NET RIA Services.

image

 

Now, add new project to the solution, selecting WCF RIA Services Library under Silverlight projects.

image

Here is what your solution will look like:

image

Go ahead and delete Class1.cs from both RIAServicesLibrary projects.  What you see here are two new project.  RIAServicesClassLibrary1.Web will be server side project, the other RIA project is client side.  Now you need to establish references.  Add a project reference to SilverlightApplication1 and point it to RIASerivcesLibrary1 project.  Add a project reference to SilverlightApplication1.Web and point it to RIAServicesLirbary1.Web.

 

Now you need to create Entity Framework item inside the RIAServicesLibrary1.Web project.

image

Follow all the step of that wizard, generating a model from the database and pointing to a new or existing server connection.  You can select all or some tables from a database.

Go ahead and build your solution now.

Now add another new item to RIAServicesLirbary1.Web project and select Domain Service Class

image

Select the Entity Framework model you just created in that wizard and select tables you would like to use on the client.

image

Rebuild the solution once more to generate Silverlight side hidden classes that support RIA Services.  You can see that code if you click on Show All Files button in Solution Explorer:

image

Now, I am going to test the setup by adding the following code to MainPage.xaml.cs.  I am going to simulate the login process by getting a specific user from my Users table and checking the password:

using System.Windows.Ria;

using System.Linq;

public partial class MainPage : UserControl

    {

        DomainService1 _context = new DomainService1();

        public MainPage()

        {

            InitializeComponent();

            Login();

        }

 

        private void Login()

        {

            var query = _context.GetUsersQuery().Where(one => one.UserName == "admin");

 

            _context.Load<Users>(query, LoadBehavior.RefreshCurrent, (o) =>

            {

                if (o.Error != null)

                    MessageBox.Show(o.Error.ToString());

                else

                {

                    if ((o.AllEntities.Count() == 1) &&

                        (o.AllEntities.First() as Users).Password == "admin")

                    {

                        MessageBox.Show("Login successfull.");

                    }

 

                    else

                    {

                        MessageBox.Show("Login failed.");

                    }

                }

            }, null); ;

        }

    }

Next we need to update web.config in SilverlightApplication1.Web project using app.config from RIAServicesLirbary1.Web project as an example.  Make sure to paste all appropriate data into correct places:

<?xml version="1.0" encoding="utf-8"?>

<configuration>

    <connectionStrings>

        <add name="RolodexEntities" connectionString="metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=.\sql2008;Initial Catalog=Rolodex;Integrated Security=True;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient" />

    </connectionStrings>

    <system.serviceModel>

        <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />

    </system.serviceModel>

    <system.web>

        <httpModules>

            <add name="DomainServiceModule" type="System.Web.Ria.Services.DomainServiceHttpModule, System.Web.Ria, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />

        </httpModules>

    </system.web>

</configuration>

Run the application now to confirm that everything is working properly.  In the next post I will explore the subject of updating the data on the server.

Post to Twitter

AppFabric Caching (Velocity) and Versioning

To continue on the topic of Velocity, I will explore versioning today.

As I showed previously, you can use DataCache.Add method to add an item to cache.  This, of course, requires that this item’s key was not to be found in the cache already, or an exception will be thrown.  This puts a damper on versioning,  So, let’s look at a different method – Put.

You can use Put method to add/replace an item in cache.  If a key already exists, the item will be replaced, otherwise it will be added.

// add an item to cache

CachablePerson person1 = new CachablePerson();

person1.FirstName = "Version1";

DataCacheItemVersion version1 = _defaultCache.Put("personwithversion", person1);

 

 

Now, I will explore versioning of items.  In order to control versioning, I will use GetAndLock method to get an item from cache while locking it to ensure safe updates.  I will update a property of an object I got from cache, then I will put it back into cache.

// get an item and lock it

DataCacheLockHandle handle;

CachablePerson temp = _defaultCache.GetAndLock("personwithversion", TimeSpan.FromSeconds(1), out handle, true) as CachablePerson;

/update an item

temp.FirstName = "Version2";

//put it back and get the new version

DataCacheItemVersion version2 = _defaultCache.PutAndUnlock("personwithversion", temp, handle);

Now I will version that versioning actually works by getting both initial and new items

// get initial item

CachablePerson ver1 = (CachablePerson)_defaultCache.Get("personwithversion");

// get the item with version 2

CachablePerson ver2 = (CachablePerson)_defaultCache.GetIfNewer("personwithversion", ref version1);

To proof that the process worked, I will output the results to a window or console.  In my case ver1.FirstName is Version1 and ver2.FirstName is Version2 which is what is expected.

In this post I looked at the Put method that makes it easier to put items into cache without worrying if an item with the same key already exists.  I also looked at the way to maintain many versioned items with the same key in cache in case versioning is important to the consuming application.

You can download the updated initial sample here.

Post to Twitter

Upcoming talks

Somehow (I am not exactly sure how) I ended up with a lot of talks that I am doing in January.  Between that and two projects I am working on simultaneously at Magenic, I have been extremely busy lately.  Those two projects will continue through end of January.

In January I will talking at Gwinnett Georgia Microsoft Users Group on SQL Azure, at Atlanta Leading Edge Microsoft Users Group on Velocity, and at Atlanta .NET Users Group on building an Azure application step-by-step.  I am also wiring an article on Entity Framework for a magazine that is due on December 31st.  Also, I am going on vacation this Saturday – my wife and I are talking our kids to Washington, DC.

I will probably be doing much blogging for a few weeks as a result.

Could I possibly have more fun than this?  Not likely.

Post to Twitter

Getting Started with Velocity (AppFabric Caching Library)

I have worked through my first Velocity project today, and I would like to blog about  the steps necessary to use caching.

First, you should read my previous post and install AppFabric on your machine.

I used Visual Studio 2010 beta 2 to create the solution.  You can download the solution here.  I create WPF project in order to prove that caching is not limited to web applications, although web farm would probably be an ideal application for caching.  Once project is created, I added references to DLLs for Velocity.  On my machine they were located in C:\Windows\System32\ApplicationServerExtensions.  Two DLLs I needed were CacheBaseLibrary.dll and  ClientLibrary.dll.  They contain key classes that can be used to utilize caching.  I could not add them directly from that folder, I was getting an error from Add Reference dialog.  So, I copied them into a folder under my Solution (“Bin” folder).

Then I added a complex class that I intended to cache.  I wanted to prove to myself that complex object graphs are OK since all the demos I saw just used strings.  Here is the class I used:

 

    public class CachablePerson

    {

        public string FirstName { get; set; }

        public string LastName { get; set; }

        public List<CachableAddress> Addresses { get; set; }

        public CachablePerson()

        {

            FirstName = "Sergey";

            LastName = "Barskiy";

            Addresses = new List<CachableAddress>();

            Addresses.Add(new CachableAddress() { Street = "Main Street", City = "Atlanta" });

            Addresses.Add(new CachableAddress() { Street = "Second Street", City = "Lilburn" });

        }

    }

 

    public class CachableAddress

    {

        public string Street { get; set; }

        public string City { get; set; }

    }

 

I put the class into its own project and referenced this project from two separate WPF application projects.

First step in using caching is to configure cache object.  Here is how we can configure cache object using cache factory:

        private void SetupCache()

        {

            DataCacheServerEndpoint[] servers = new DataCacheServerEndpoint[1];

            servers[0] = new DataCacheServerEndpoint("Sergey-Laptop", 22233, "DistributedCacheService");

            _cacheFactory = new DataCacheFactory(servers, false, true);

            _defaultCache = _cacheFactory.GetCache("default");

        }

 

Now we are ready to add object to cache.  We will do this in steps.  First we check to see if an object is already in cache, and if so, we will remove it from cache.  Cache basically is using a string as the object key.  In addition to that you can also version objects, thus having multiple copies of the same object with the same key existing in cache at any given time.

            if (_defaultCache.Get("person") != null)

            {

                _defaultCache.Remove("person");

            }

            _defaultCache.Add("person", _person);

 

 

Now I am going to get the object from cache.  Just as simple as adding it:

_person = (CachablePerson)_defaultCache.Get("person");

 

Simple and easy.  I think Velocity is super powerful yet simple to use.  Event though it would be an abuse, but one could possibly use caching to communicate between different applications. 

You can download my sample solution here

Post to Twitter

Windows AppFabric and Velocity

I downloaded Windows AppFabric Beta 1 version this week.  You can find this download here. It took a few hours to install it.  I could surely tell I was dealing with beta 1 of version 1 of the product.  I finally installed it using new cluster option and XML configuration option.  I tried SQL Server configuration  option a few times, but it never installed without errors.  I think at the end I ran the install about a dozen times before it succeeded.

Anyway, three hours later or so I was done.  Next I tried to run a downloaded sample.   No matter what I tried, I could not get the sample to work.  It looked pretty obvious that I still need to configure something.  Finally after another 30 minutes I found an answer – I had to start the cache cluster.  To do so, I went to Programs –> Microsoft Distributed Cache –> Administration tool.  I was sort of surprised that this launched PowerShell window.  I guess we need to wait until release to get real nice configuration software with GUI.  In the mean time, I had to type “start-cachecluster”.  Once I ran that and saw that the server was started, I went back to run the samples.  They worked perfectly well this time.

Once I write my own sample, I will post source code on this blog.

Post to Twitter

Windows Azure Application

This is purely a bragging post :-)

I just deployed a test application to the cloud (Microsoft Azure): http://rolodex.cloudapp.net/

Here is the technology stack for it:

  1. Windows Azure
  2. SQL Azure
  3. CSLA 3.8.1
  4. Silverlight
  5. Entity Framework
  6. WCF
  7. Prism (Composite Application Guidance)
  8. Silverlight Toolkit

I promise to write a blog entry in the near future, the steps one has to follow through to create an Azure application.

Post to Twitter

Dynamically Styling Silverlight Applications

I spoke at GGMUG (Gwinnett Georgia Microsoft Users Group) on Thursday.  I was speaking about dynamically styling Silverlight applications using Implicit Style Manager from Silverlight Toolkit

Silverlight toolkit comes with about a dozen themes that anyone can use to style there applications.  In the example I am posting I use four of them,  A theme file is essentially a XAML file that contains styles for all native Silverlight controls as well as all Toolkit controls.  Implicit style manager allows developers to dynamically (or statically) load a theme and apply it to any FrameworkElement in the visual tree. 

There are only a few steps you need to do to implement this type of styling.

1.  Download and install Toolkit.

2.  Create new Silverlight application.

3.  Create new folder under applications (UserThemes in my example) and copy some or all themes from toolkit (C:\Program Files\Microsoft SDKs\Silverlight\v3.0\Toolkit\Oct09\Themes is the default folder) into that folder.  Once you include all the themes into the project, set compile action to Content.

4.  Now write a few lines of code in key places to apply a chosen theme.  Here is what this code would look like:

        private void ApplyeTheme(string themeName)

        {

            Uri uri = new Uri(string.Concat("UserThemes/", themeName, ".xaml"), UriKind.Relative);

            ImplicitStyleManager.SetResourceDictionaryUri(this, uri);

            ImplicitStyleManager.SetApplyMode(this, ImplicitStylesApplyMode.OneTime);

            ImplicitStyleManager.Apply(this);

        }

5.  You can even allow application user to select a theme by creating for example a combo box loaded with available themes.

Implicit style manager does carry some overhead with it.  To minimize the overhead try to use apply mode of OneTime.  Ap0ply mode of Auto will watch for LayoutUpdated event and restyle attached element.  If you use this mode, you can apply this code to your shell (outer application frame), and any loaded control will be styled.  It sounds easy, but it will slow down your application.

As you can see, you cheaply and easily implement dynamic styling using free! software from Silverlight Toolkit.

You can download full example here.

Post to Twitter

Rocky Lhotka is Talking Oslo at ALEMUG

At out next Atlanta Leading Edge Microsoft Users Group Rocky Lhotka will be talking about Oslo.  Please visit ALEMUG.NET home page to register for this exciting event!

Here are the details of this event.

Microsoft code-name “Oslo” includes the ability to define your own domain specific  language (DSL), a metadata repository hosted in SQL Server and a graphical tool (“Quadrant”) to edit that metadata. One part of the Oslo vision is that you might define a DSL, build code in your language, compile that code into the repository and then create a runtime to dynamically execute that metadata. Taking this vision and combining it with the popular CSLA .NET framework, the result is MCsla. This is a prototype DSL grammar, repository schema and runtime that dynamically creates and executes CSLA .NET business objects with a WPF UI. The result is a fully functional application that you can create with a fraction of the code you’d need to write with traditional programming techniques. Learn how MCsla was created and how it works in this rapid-fire walk through the depths of the Olso technology.

Rockford Lhotka is the creator of the popular CSLA .NET development framework, and is the author of numerous books, including Expert C# 2008 Business Objects and Expert VB 2008 Business Objects. He is a Microsoft Regional Director, MVP and INETA speaker. He contributes to several major magazines and regularly presents at major conferences around the world. Rockford is the Principal Technology Evangelist for Magenic (www.magenic.com), a company focused on delivering business value through applied technology and one of the nation’s premiere Microsoft Gold Certified Partners. For more information go to www.lhotka.net.

Post to Twitter

Getting Started with SQL Azure

I setup an account with SQL Azure last week, and I would like to document each step I took in order. 

There is a lot of information on SQL Azure FAQ and Zack Owens’ blog.  I still ran into some issues though, and I wanted to provide detailed instruction on how to work through them.

Step 1 – Get SQL Azure token.  You need to Microsoft Azure site and scroll down the page to request tokens.

Step 2 – Wait for the email you will receive that will contain the token (invitation code) and instructions on how to activate it. Follow those step to setup an account.

Step 3 – Create new project in SQL Azure.  You will setup user ID and password as part of that process.

Step 4 – Create a database with a name you choose and setup firewall

image

 

image 

 

image

You can see your own IP address on this window above as well.  You can just copy that address and paste it into both IP ranges – low and high,

Step 5 – Start SSMS (SQL Server Management Studio).  Hit Cancel on initial login screen.

image

Step 6 – Click New Query button

image

Step 7 – Enter your server information, but do NOT click Connect

image

Step 8 – Click Options and enter your database name

image

Step 9 – Click “Connect”.  You should not get any errors and now you can see a query window.  You are ready to add tables.

Step 10 – Type in script to create database structure.  Important: not all standard SQL commands are supported.  If you are scripting an existing database, you will need to remove all file group references, such as “ON PRIMARY”. 

image

Step 11 – Create a standard .NET application.  You can get exact connection string on your SQL Azure management page:

image

You are done!

Find more information on SQL Azure FAQ and Zack Owens’ blog.

Post to Twitter

Entity Framework 4.0 CTP

I just installed CTP of entity framework 4.0 (2.0 technically).  I decided to test the most advertized feature – ability to have actual foreign keys (IDs) in addition to navigation properties.  The lack of this feature has been the biggest annoyance for me while working with Entity Framework for many months now.

Here is the model I created

image

As you can see Companies have Contacts, and each contact object now has CompanyID in addition to Company navigation property.  I had to select this option while generating the model from the database.  The checkbox for option to include foreign key values was available on one of the wizard screens.

Here is the code I wrote for testing:

 

            using (RolodexEntities context = new RolodexEntities())

            {

                CompanyContact newConact = new CompanyContact();

                newConact.CompanyId = 2;

                newConact.BaseSalary = 1;

                newConact.Birthday = DateTime.Today;

                newConact.FirstName = "Sergey";

                newConact.LastName = "Barskiy";

                newConact.RankId = 1;

                context.AddToCompanyContacts(newConact);

                context.SaveChanges();

            }

Hurray!  It worked!  New contact was added to the database and linked to Company with ID of 2 and Rank with ID of 1.

This feature to me is invaluable in n-Tier development when a developer has to replay the changes on the server after allowing the user to edit the data on the client.  Now, we can just transmit all properties of a Contact to the server, (probably with IsNew, IsUpdated, IsDeleted flags), set the foreign keys via IDs, then save.

Post to Twitter

Silverlight 3 – CollectionViewSource and Navigation

I am killing two birds with one stone in this post, covering both CollectionViewSource and Navigation framework in Silverlight 3.

To create new Silverlight application that uses Navigation framework, simply create new project in Visual Studio, and you will find Silverlight Navigation Application project template under Silverlight node.  Navigation framework in Silverlight three allows developers to create navigation structure that mimics the one of ASP.NET (or any web allocation for that matter).   In other words, this framework provide for URI driven navigation, using Uri routing feature similar to ASP.NET MVC framework.  Of course, this is really from end user perspective, not developer.  Obviously, Silverlight application cannot navigate from one to another XAML page using browser natively.  As a result, navigation framework utilizes browser bookmark feature in order to provide the user with Next/Previous navigation using actual browser buttons.  Routing engine enables the mapping between short Uri and actual XAML page that is supposed to handle the navigation event to this Uri.  Here is what this routing looks like:

            <navigation:Frame x:Name="ContentFrame" Style="{StaticResource ContentFrameStyle}"

                             Source="/Home" Navigated="ContentFrame_Navigated" NavigationFailed="ContentFrame_NavigationFailed">

                <navigation:Frame.UriMapper>

                    <uriMapper:UriMapper>

                        <uriMapper:UriMapping Uri="" MappedUri="/Views/Home.xaml"/>

                        <uriMapper:UriMapping Uri="/{pageName}" MappedUri="/Views/{pageName}.xaml"/>

                        <uriMapper:UriMapping   

                           Uri="ProductDetail/{ProductId}"   

                           MappedUri="/Views/ProductDetail.xaml?ProductId={ProductId}"/>

                    </uriMapper:UriMapper>

                </navigation:Frame.UriMapper>

            </navigation:Frame>

Here is how we read this code.  The core part of navigation is Frame control.  It handles browser interaction and provide Uri mapping.  If we look at the mapper XAML, we will see that short Uri, such as “” (blank) maps to Home.Xaml.  Home.Xaml is not User Conrol, it inherits from Page control, another part of navigation framework.  Any XAML page that is supposed to handle navigation must inherit from Page.  The mapper supports tokenization as well, that is how {pageName} is mapped to /Views/{pageName}.xaml.  So, if we navigate to Uri “Home”, /Views/Home.xaml will be loaded into the frame. For example, we have HyperLinkButton as follows:

                    <HyperlinkButton x:Name="Link2" Style="{StaticResource LinkStyle}"

                                    NavigateUri="/About" TargetName="ContentFrame" Content="about"/>

In this case when user clicks on this button, he/she will be navigated to /Views/About.xaml that will be shown in Frame called ContentFrame.

Navigation framework also supports parameters, and incidentally it took me an hour to figure those out.  In the example above our ProductDetail mapping supports parameter called PrductId.  So, far pretty easy.  The hard part is to figure out how to set that Url.  In my case, I have a product object, and I am setting the Url in it to match my mapping.  Here is full source code for Product class and collection of products:

using System;

 

namespace SilverlightNavigationApp

{

    public class Product

    {

        public string ProductId { get; set; }

        public string ProductName { get; set; }

        public string ProductDescription { get; set; }

        public Uri Url { get; set; }

    }

}

using System;

using System.Collections.ObjectModel;

 

namespace SilverlightNavigationApp

{

    public class ProductList : ObservableCollection<Product>

    {

        public ProductList()

        {

            Add(new Product() { ProductId = "1", ProductName = "Bread", ProductDescription = "Wheat bread.", Url = new Uri("ProductDetail/1", UriKind.Relative) });

            Add(new Product() { ProductId = "2", ProductName = "Milk", ProductDescription = "Whole milk.", Url = new Uri("ProductDetail/2", UriKind.Relative) });

            Add(new Product() { ProductId = "3", ProductName = "Potatoes", ProductDescription = "Red potatoes.", Url = new Uri("ProductDetail/3", UriKind.Relative) });

            Add(new Product() { ProductId = "4", ProductName = "Water", ProductDescription = "Bottled water.", Url = new Uri("ProductDetail/4", UriKind.Relative) });

            Add(new Product() { ProductId = "5", ProductName = "Cake", ProductDescription = "Chocolate cake.", Url = new Uri("ProductDetail/5", UriKind.Relative) });

        }

    }

}

So far so good.  You can see how Url must be formatted to match product Id. I am showing product list inside a page using DataGrid.

<navigation:Page x:Class="SilverlightNavigationApp.Views.ProductList"

   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   xmlns:local="clr-namespace:SilverlightNavigationApp"

   xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"

   xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"

   >

    <UserControl.Resources>

 

        <CollectionViewSource Source="{StaticResource ProductList}" x:Key="ViewSource" Filter="MyFilter"/>

    </UserControl.Resources>

    <Grid x:Name="LayoutRoot">

        <Grid.RowDefinitions>

            <RowDefinition Height="Auto"/>

            <RowDefinition Height="*"/>

        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>

            <ColumnDefinition Width="Auto"/>

            <ColumnDefinition Width="*"/>

        </Grid.ColumnDefinitions>

        <TextBlock Text="Fitler:"/>

        <TextBox Grid.Column="1" TextChanged="TextBox_TextChanged" x:Name="FilterBox" Text=""/>

        <data:DataGrid

           ItemsSource="{Binding Source={StaticResource ViewSource}}"

           AutoGenerateColumns="False"

           Grid.Row="1"

           Grid.ColumnSpan="2">

            <data:DataGrid.Columns>

                <data:DataGridTextColumn Binding="{Binding ProductId}" Header="Product ID"/>

                <data:DataGridTextColumn Binding="{Binding ProductName}" Header="Product Name"/>

                <data:DataGridTextColumn Binding="{Binding ProductDescription}" Header="Description"/>

                <data:DataGridTemplateColumn>

                    <data:DataGridTemplateColumn.CellTemplate>

                        <DataTemplate>

                            <Button Content="Details" Tag="{Binding Url}" Click="Button_Click"/>

                        </DataTemplate>

                    </data:DataGridTemplateColumn.CellTemplate>

                </data:DataGridTemplateColumn>

            </data:DataGrid.Columns>

        </data:DataGrid>

    </Grid>

</navigation:Page>

You can see that I am setting the tag for the button to Url property of the Product object.  Here is how I am processing this information in click event:

        private void Button_Click(object sender, RoutedEventArgs e)

        {

            NavigationService.Navigate(((Button)sender).Tag as Uri);

        }

Here is what we can do with this in the Details page:

        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)

        {

            string productId = this.NavigationContext.QueryString["ProductId"].ToString();

            SilverlightNavigationApp.ProductList list = (SilverlightNavigationApp.ProductList)App.Current.Resources["ProductList"];

            Product product = (from one in list

                               where one.ProductId == productId

                               select one).FirstOrDefault();

            this.DataContext = product;

        }

Alternatively, I can use propertied of HyperLinkButton to do the same if I do not need to use dynamic parameters.  Look above for About navigation.

Now, let’s talk about ColllectionViewSource.  It suports grouping, sorting and filtering.  In the example I will use filtering technique.  The filtering is pretty easy – we just subscribe to filter event, evaluate each object, and decide whether or not show it:

    <UserControl.Resources>

        <CollectionViewSource Source="{StaticResource ProductList}" x:Key="ViewSource" Filter="MyFilter"/>

    </UserControl.Resources>

        private void MyFilter(object sender, FilterEventArgs e)

        {

            Product product = e.Item as Product;

            if (FilterBox != null)

            {

                e.Accepted = product.ProductName.ToUpper().Contains(FilterBox.Text.ToUpper()) ||

                    product.ProductDescription.ToUpper().Contains(FilterBox.Text.ToUpper());

            }

            else

                e.Accepted = true;

        }

All that is left is to call refresh when we want to response to use actions:

        <TextBox Grid.Column="1" TextChanged="TextBox_TextChanged" x:Name="FilterBox" Text=""/>

        private void TextBox_TextChanged(object sender, TextChangedEventArgs e)

        {

            CollectionViewSource source = this.Resources["ViewSource"] as CollectionViewSource;

            source.View.Refresh();

        }

Pretty simple.  You can download full example here.

Post to Twitter

Silverlight 3.0 Behaviors – Part 2

Today I am going to explore Silverlight three behaviors a little more.  In this post I am going to look at different events that can trigger an action in a behavior.  Essentially, we can specify any event on a target element to invoke a behavior. 

Again, we are going to use TargetedTriggerAction base class. This time however we are going to enable this behavior to be able to be used on a larger suite of targets.  We are going to use UIElement as the target type: TargetedTriggerAction<UIElement>.  We are only going to override one method – InvokeAction.  Here is what the class looks like:

    public class MakeLargerSmallerAction : TargetedTriggerAction<UIElement>

    {

        protected override void Invoke(object parameter)

        {

            StoryBoardHelper.PlayControlAnimation(Target, Percent);

        }

Here are a couple of things I need to explain. 

  1. This behavior is going to perform one function – change dimensions (increase or decrease the size) of the target control base on an event.  We are going to add a property that would allow our behavior to specify the factor by which the target’s size needs to increase or decrease.
  2. We are going to use animations to perform this function.  We will build animations in code.
  3. We will invoke animations based on event specified in XAML.

Here is full source code for behavior class:

using System;

using System.Windows.Interactivity;

using System.Windows;

 

namespace Behaviors

{

    public class MakeLargerSmallerAction : TargetedTriggerAction<UIElement>

    {