Skip to content
Archive of entries posted by

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

 

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.