Enabling NetTcpBinding for Performance gains and binary serialization

I have a web simple web service which as just basic http binding, below are the steps to steps to enable netTcpBinding

<services>
      <service name="TestWcfWebService.Service.PersonService">
        <endpoint address="basic" binding="basicHttpBinding" bindingConfiguration="" 
          contract="TestWcfWebService.Contracts.IPerson" />
</service>

My webservice is at http://localhost/TestWcfWebService-Server/Service.svc?wsdl

Below you can see the methods when you add reference to this service using wcfTestclient

All the methods work fine.

Let us add another endpoint with netTcpBinding

 <services>
      <service name="TestWcfWebService.Service.PersonService">
        <endpoint address="basic" binding="basicHttpBinding" bindingConfiguration="" 
          contract="TestWcfWebService.Contracts.IPerson" />
        <endpoint address="tc" binding="netTcpBinding" bindingConfiguration="" 
                  contract="TestWcfWebService.Contracts.IPerson" />
          </service>
    </services>

When you browse to the svc file you will get an error

Could not find a base address that matches scheme net.tcp for the endpoint with binding NetTcpBinding. Registered base address schemes are [http].

I am using Windows7 , IIS7, App pool 4.0 Integrated. What the error is telling is you have not enabled the net.tcp binding protocol on you website. Go to your application, right click, manage application, and advance setting

Add net.tcp to the Enabled Protocol

Now browse to the svc file.

Now let us try to add reference to this service using wcfTestClient

You can see now we have the net Tcp endpoint, http binding still works fine, when you try to invoke addPerson you get error

Could not connect to net.tcp://localhost/TestWcfWebService-Server/Service.svc/tc. The connection attempt lasted for a time span of 00:00:02.0112011. TCP error code 10061:

The reason for this error is because your Net.Tcp Listener Adapter Service is not started.

When you try to start Net.Tcp Listener Adapter Service you may get the below error

Windows could not start the Net.Tcp Listener Adapter service on Local Computer.
Error 1068: The dependency service or group failed to start.
This error is because Net TCP depends on Net.Tcp Port Sharing and Windows Process Activation Service, make sure these services are started as well.

After these services are started Net TCP Binding is all set.

Below is the code in VB when you need to invoke a specific end point after adding service reference, first look at the wsdl on the client after adding reference, you will find the endpoint name BasicHttpBinding_IPerson and NetTcpBinding_IPerson

My WSDL

<wsdl:service name="PersonService">
    <wsdl:port name="BasicHttpBinding_IPerson" binding="tns:BasicHttpBinding_IPerson">
      <soap:address location="http://localhost/TestWcfWebService-Server/Service.svc/basic" />
    </wsdl:port>
    <wsdl:port name="NetTcpBinding_IPerson" binding="tns:NetTcpBinding_IPerson">
      <soap12:address location="net.tcp://localhost/TestWcfWebService-Server/Service.svc/tc" />
      <wsa10:EndpointReference> 

Here I am invoking net tcp binding endpoint.

    Private Sub Form1_Load(ByVal sender As System.ObjectByVal e As System.EventArgsHandles MyBase.Load 
        client = New PersonClient("NetTcpBinding_IPerson") 
    End Sub 

Possible other errors you may encounter

I am using NetworkService as the Identity of the application pool running this WCF service application.

When I try to add reference I get the below error

The document was understood, but it could not be processed.

– The WSDL document contains links that could not be resolved.

– There was an error downloading ‘http://localhost/TestWcfWebService-Server/Service.svc?xsd=xsd0&#8217;.

– The underlying connection was closed: An unexpected error occurred on a receive.

– Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.

– An existing connection was forcibly closed by the remote host

Metadata contains a reference that cannot be resolved: ‘http://localhost/TestWcfWebService-Server/Service.svc?wsdl&#8217;.

There was no endpoint listening at http://localhost/TestWcfWebService-Server/Service.svc?wsdl that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.

The remote server returned an error: (404) Not Found.

If the service is defined in the current solution, try building the solution and adding the service reference again.

This error is because of the pool identity does not have the right privileges to C:\windows\Temp, when I ran the pool with identity as myself no problem,

MvcSiteMap Provider BreadCrumbs

The below demo will show how to use MvcSiteMap Provider to do breadcrumbs in your MVC web project

Start with an empty MVC3 web application
image

image

There are a couple ways to get to MvcSiteMap
1. Using NuGet
2. Manually configuring MvcSiteMap Provider

If you use NuGet most of the work will be done for you, open the Package Manager Console and type in the following command and hit enter

PM> Install-Package MvcSiteMapProvider

The dll will be downloaded,MVC.SiteMap will be created, references will be added and a few web.config file entries will be made. If you wish to do it all by yourself then follow option 2

Manually configuring MvcSiteMap Provider

Download the dll from http://mvcsitemap.codeplex.com/

To your empty Mvc project add reference to MvcSiteMapProvider.dll by browsing to the location where you downloaded the dll.

image

Make sure CopyLocal is set to true, by default it is set to false.

image

Let us add few controllers and views to test out the breadcrumbs

Add HomeController

image

Add the view for Index Action

image

Update the Index.vbhtml to

Code Snippet
  1. @Code
  2. ViewData(“Title”) = “Home Index”
  3. End Code
  4. <h2>Home Index</h2>

Add another controller call it application

image

Add the view for Index action in the application controller

image

Update Application Index.vbhtml to look like below

Code Snippet
  1. @Code
  2. ViewData(“Title”) = “Application Index”
  3. End Code
  4. <h2>Application Index</h2>

We will add another action to the application controller, let us call it SpecialApp

Code Snippet
  1. Function SpecialApp(ByVal id As Integer) As ActionResult
  2. ViewBag.appId = id
  3. Return View()
  4. End Function

Add a view to the SpecialApp action as described before

Code Snippet
  1. @Code
  2. ViewData(“Title”) = “SpecialApp”
  3. End Code
  4. @ViewBag.appId
  5. <h2>SpecialApp</h2>

Let us add another controller called Account and then add Index view for this controller

Code Snippet
  1. @Code
  2. ViewData(“Title”) = “Accounts Page”
  3. End Code
  4. <h2>Acoounts Page</h2>

Now let us add the Mvc.sitemap

image

As you can see now I have 3 controllers and few views

image

But the way I want to arrange my website is as below

image

In order to achieve this let us modify the Mvc.sitemap to

Code Snippet
  1. <?xmlversion=1.0encoding=utf-8 ?>
  2. <mvcSiteMapxmlns=http://mvcsitemap.codeplex.com/schemas/MvcSiteMap-File-3.0enableLocalization=true>
  3.   <mvcSiteMapNodetitle=Homecontroller=Homeaction=Index>
  4.     <mvcSiteMapNodetitle=Applicationcontroller=Applicationaction=Index>
  5.       <mvcSiteMapNodetitle=Special Applicationscontroller=Applicationaction=SpecialApp/>
  6.     </mvcSiteMapNode>
  7.       <mvcSiteMapNodetitle=Accounts Pagecontroller=Accountaction=Index/>
  8.   </mvcSiteMapNode>
  9. </mvcSiteMap>

Now to show the breadcrumbs you need to add a template view called SiteMapPathHelperModel.vbhtml, before that right click the project select properties and add MvcSiteMapProvider.web.html and add MvcSiteMapProvider.Web.Html.Models to the imported namespaces

image

Under the shared folder make a new folder called DisplayTemplates (I had big problems since I had space between Display and Templates so make sure there is not space) and then add a new view call it SiteMapPathHelperModel.vbhtml

Code Snippet
  1. @imports System.Web.Mvc.Html
  2. @imports System.Linq
  3. @imports MvcSiteMapProvider.Web.Html.Models
  4. @ModelType SiteMapPathHelperModel
  5. @For Each node In Model
  6. @Html.ActionLink(node.Title, Nothing, New With {.Controller = node.Controller, .action = node.Action})
  7. If node IsNot Model.Last() Then
  8. @<text> &gt; </text>
  9. End If
  10. Next

Here for each node I make an html actionLink, then add a > sign except for the last node
Now in order to display the breadcrumbs lets edit the _Layout.vbhtml,
Add @imports MvcSiteMapProvider.Web.Html

Change

Code Snippet
  1. <body>
  2. @RenderBody()
  3. </body>

To

Code Snippet
  1. <body>
  2. <p>Breadcrumbs:</p>
  3. @Html.MvcSiteMap().SiteMapPath()
  4. @RenderBody()
  5. </body>

Now when you run the application you will see the error screen “The file web.sitemap required by XmlSiteMapProvider does not exist”.
That is because we have still not told the Framework what SiteMapProvider we are using. In order to do that open the application web.config file and place the below code inside system.web tag

Code Snippet
  1. <siteMapdefaultProvider=MvcSiteMapProviderenabled=true>
  2. <providers>
  3. <clear />
  4. <addname=MvcSiteMapProvidertype=MvcSiteMapProvider.DefaultSiteMapProvider, MvcSiteMapProvidersiteMapFile=~/Mvc.SitemapsecurityTrimmingEnabled=truecacheDuration=5enableLocalization=truescanAssembliesForSiteMapNodes=trueincludeAssembliesForScan=“”excludeAssembliesForScan=“”attributesToIgnore=visibilitynodeKeyGenerator=MvcSiteMapProvider.DefaultNodeKeyGenerator, MvcSiteMapProvidercontrollerTypeResolver=MvcSiteMapProvider.DefaultControllerTypeResolver, MvcSiteMapProvideractionMethodParameterResolver=MvcSiteMapProvider.DefaultActionMethodParameterResolver, MvcSiteMapProvideraclModule=MvcSiteMapProvider.DefaultAclModule, MvcSiteMapProvidersiteMapNodeUrlResolver=MvcSiteMapProvider.DefaultSiteMapNodeUrlResolver, MvcSiteMapProvidersiteMapNodeVisibilityProvider=MvcSiteMapProvider.DefaultSiteMapNodeVisibilityProvider, MvcSiteMapProvidersiteMapProviderEventHandler=MvcSiteMapProvider.DefaultSiteMapProviderEventHandler, MvcSiteMapProvider />
  5. </providers>
  6. </siteMap>

When you run the application you will see, the breadcrumbs show up
image
image

Using attributes

MvcSiteMap Provider also as the ability to mark the action methods with attributes to link up the sitemap. Let us say I have an action called HomeApp in the application controller

Code Snippet
  1. Function HomeApp(ByVal id As Integer) As ActionResult
  2. ViewBag.appId = id
  3. Return View()
  4. End Function

but I want this link to show up after the home index in the breadcrumbs. What I need to do is add a key to the home node as below

Code Snippet
  1. <mvcSiteMapNodetitle=Homecontroller=Homeaction=Indexkey=Home1>

Then add attributes to the action method

Code Snippet
  1. <MvcSiteMapNode(Title:=“Home Applications”, ParentKey:=“Home1”)>
  2. Function HomeApp(ByVal id As Integer) As ActionResult
  3. ViewBag.appId = id
  4. Return View()
  5. End Function

You will have to add Imports MvcSiteMapProvider at the top of the controller
Now when you run the app
image

Access Sharepoint list from .Net 3.5 as Web Service using CAML

Today I had a need to access a sharepoint list that was on our intranet site, I had to consume this list from a .net application. I used Lists.asmx web service for this. In this example I will be using .net 3.5 in the next post I want to show using .net 4.0

As always I just used a simple windows forms application to test this. After I created a new windows forms project, I added the service reference, on the Add service Reference click Advanced… and in the Service Reference Settings click Add Web Reference, this will let you add web reference in the traditional way as was done in .net 2.0

image

The url for my list.asmx was at location http://intranet.xxxxx/_vti_bin/lists.asmx

I gave the web reference name xxxSPList

image

On button1 click I wrote the code to query the list, I have commented the code so should be self explanatory

Code Snippet
  1. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
  2.         ‘Create a new instance of the proxy class to access the list
  3.         Dim ws As New xxxSPList.Lists
  4.         ‘Setup security
  5.         ‘If you are using a specfic userID and password to access the list use the line below
  6.         ‘ws.Credentials = New System.Net.NetworkCredential(“useridgoeshere”, “passwordgoeshere”, “domainnamegoeshere”)
  7.         ‘If you want to use the currently logged on user creddentials, use the line below
  8.         ws.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials
  9.         ‘Create a new xml document to query the web service
  10.         Dim queryDocument = New XmlDocument
  11.         Dim queryNode As XmlNode = queryDocument.CreateElement(“Query”)
  12.         ‘The actual CAML query, here systemName is a variable value that I am embedding inside the query, basically my sharepoint list as
  13.         ‘column called Application, I want to query that coulmn for a specific name
  14.         Dim systemName = “CDOL”
  15.         queryNode.InnerXml = “<Where><Eq><FieldRef Name=’Application’ /><Value Type=’Text’>” & systemName & “</Value></Eq></Where>”
  16.         ‘In the selectFields choose the columns from the list that need to appear in the query result
  17.         Dim selectFields As XmlNode = queryDocument.CreateElement(“ViewFields”)
  18.         selectFields.InnerXml = “<FieldRef Name=’Title’/><FieldRef Name=’Alert_x0020_Description’ />” & _
  19.                                 “<FieldRef Name=’Message_x0020_Expiration_x0020_Date’ /><FieldRef Name=’Priority’ /> “
  20.         ‘In use the lists guid to query. If you do not know how to get the guid for list, below is asimple trick.
  21.         ‘Go the list in the sharepoint, select the value uin the first column right click properties
  22.         ‘and in the address you should be able to fnd the guid
  23.         Dim result = ws.GetListItems(“{26C62B2E-5E40-4D2D-BF3C-B510938B4181}”, Nothing, queryNode, selectFields, Nothing, Nothing, Nothing)
  24.         Dim xData = XElement.Parse(result.InnerXml)
  25.         Dim alerts As New List(Of Alert)
  26.         For Each x In xData.DescendantsAndSelf(XName.Get(“row”, “#RowsetSchema”))
  27.             alerts.Add(New Alert With {.Title = GetAttributeValue(x.Attribute(“ows_Title”)), _
  28.                                        .Description = GetAttributeValue(x.Attribute(“ows_Alert_x0020_Description”)), _
  29.                                        .ExpirationDate = GetAttributeValue(x.Attribute(“ows_Message_x0020_Expiration_x0020_D”)), _
  30.                                        .Priority = GetAttributeValue(x.Attribute(“ows_Priority”)), _
  31.                                        .ID = x.Attribute(“ows_UniqueId”).Value _
  32.                                     })
  33.             ‘Todo: strip out on the guid inside the {}
  34.         Next
  35.     End Sub
  36.     Private Function GetAttributeValue(ByVal att As System.Xml.Linq.XAttribute) As String
  37.         Return If(att Is Nothing, Nothing, att.Value)
  38.     End Function

Export Tab Delimited text file in SSRS 2008 R2

Locate rsreportserver.config in the server, and add the below lines of code

Code Snippet
  1. <ExtensionName=TABType=Microsoft.ReportingServices.Rendering.DataRenderer.CsvReport,Microsoft.ReportingServices.DataRendering>
  2.                 <OverrideNames>
  3.                      <NameLanguage=en-US>TAB (Tab Delimited Text File)</Name>
  4.                 </OverrideNames>
  5.                 <Configuration>
  6.                           <DeviceInfo>
  7.                                <FieldDelimiterxml:space=preserve>    </FieldDelimiter>
  8.                            <UseFormattedValues>False</UseFormattedValues>
  9.                                <NoHeader>False</NoHeader>
  10.                       <FileExtension>Txt</FileExtension>
  11.                           </DeviceInfo>
  12.                       </Configuration>
  13.             </Extension>

I added it right below CSV extension

I did a few things with the TAB extension, I named the Extension “TAB”, I Named in  TAB (Tab Delimited Text File) this the name that is displayed in the reports webpage when you click the export option

image

I wanted the file extension to be .txt, so I mention <FileExtension>Txt</FileExtension>
I wanted the Column Header in the tab delimited file so <NoHeader>False</NoHeader>

Dynamically compare 2 entity property values in VB.net

Had a scenario today where we had to compare the property values of view model against a domain entity, so I wrote simple windows client sample to dynamically compare properties with the same name to dynamically compare values and if the values are different just add the names of these properties to a list

On Load I create 2 entities _person and _student; person has name and age properties; _student has name, age, sex and school. On comparing _person and _student we find “name” property values differ, age is same, sex and school does not apply to person class. So the only property I want in difference list is “name”

Code Snippet
  1. Public Class Form1
  2.     Private _person As Person
  3.     Private _student As Student
  4.     Private Sub Compare_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Compare.Click
  5.         Dim diffList As New List(Of String)
  6.         For Each personProp In _person.GetType.GetProperties
  7.             Dim studentValue = _student.GetType.GetProperty(personProp.Name).GetValue(_student, Nothing)
  8.             Dim personValue = _person.GetType.GetProperty(personProp.Name).GetValue(_person, Nothing)
  9.             If studentValue <> personValue Then
  10.                 diffList.Add(personProp.Name)
  11.             End If
  12.         Next
  13.     End Sub
  14.     Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
  15.         _person = New Person With {.name = “A”, .age = 10}
  16.         _student = New Student With {.name = “B”, .age = 10, .sex = “m”, .school = “XYZ”}
  17.     End Sub
  18. End Class

Code first – Enums Supported in EF June 2011 CTP

Support for enumeration has been one of the long desired requests in Entity Framework. As soon as I saw the June 2011 CTP, I had to test it. Here is what I did

1. I created windows project TestEfJuneCtp

image

2. I changed the Target framework to “Microsoft Entity Framework June 2011 CTP”

image

3.    Created a couple of classes project, order and an enumeration ProjectStatusType

 

image

4.    Project has a property projectStatus of type ProjectStatusType, this would have been ignored in EF 4.1. meaning when you generate the database projectStatus column would not appear in the project table. Now in the current CTP it does appear of type Int.

5.    Then I set up my Context, I did add reference to system.data.entity v4.2

image

6.    Using Enums to set values

image

7.    If you want to set value other than the one in Enum then just Directcast
image
8.    Since I set projectStatus to InProgress, it is set to 0 in the database column
9.    Get Values from Enum properties

image

When you do projectEntity.projectStatus it returns “0”, but when you do do projectEntity.projectStatus.ToString it returns “InProgress”

10.    Also the power of enumeration can be more profound when writing code sinec intellisence can pick up the type

Concurrency in Entity Framework 4.1 code first.

Let us assume we have a person entity and it looks as below

Imports System.ComponentModel.DataAnnotations
Public Class Person

    Public Property ID As Integer
    <StringLength(50)>
    Public Property FirstName As String
    <Timestamp()>
    Public Property RowVersion As Byte()

End Class

Using EF 4.1 and code first, a typical update would look as show below

       Using entities = New EFConcurrencyTestContext
            Try
                Dim personEntity = entities.People.Where(Function(p) p.ID = 1).FirstOrDefault
                personEntity.FirstName = "CCC"
                entities.SaveChanges()
            Catch concurrencyException As DbUpdateConcurrencyException
                Throw New Exception("The record u r trying to update has changed")
            Catch ex As Exception
                Throw New Exception("Some Exception")

            End Try
        End Using
Since our main focus is to test Concurrency, let put a break point at the line Highlighted, start debugging when the debugger stops at personEntity.FirstName = "CCC", in the database update the person firstname, then continue debugging, on the savechanges you would get a DbUpdateConcurrencyException. This is pretty straight forward and works as expected. Let’s take a different scenario, for e.g. in multi tier MVC application

1.    In the service layer I would do get person, say the person FirstName is ‘A’, RowVersion is 1
2.    I would then build a ViewModel, take only a few data elements from person entity I need for the viewModel, I don’t transfer the person entity across tiers, meaning my controller only know about my viewmodel and is unaware of my domain object which is person. In order to check for Concurrency I will create a property in my ViewModel called PersonRowVersion and store the rowversion in it.
3.    As the data is being manipulated by my view, let us assume the record in the database was updated as well.  Say FirstName in the Database is ‘B’ and RowVersion is 2
4.    Now my View modified the person FirstName to ‘C’, I had stored my RowVersion either using a hidden field or in the Tempdata. I build the ViewModel, take the modified FirstName which is ‘C’ and restore the RowVersion from my hidden field which is 1
5.    In the service layer, I get the person entity from the database, which will have the FirstName = ‘B” and RowVersion = “2”. I update the FirstName to “C” and RowVersion to “1” and do Context.Savechanges. The update happens but no concurrency exception is raised
6.    In order to get the Concurrency Exception you will have to modify the OriginalValue of the property that is used for tracking concurrency, in my case it is RowVersion. Something like this

entities.Entry(personEntity).Property("RowVersion").OriginalValue = _rowVersion

I have created a few test cases (Windows client application) to mimic this process. The idea is to show what works and what does not.

Imports System.Data.Entity.Infrastructure

Public Class Form1

    Private _fName As String
    Private _rowVersion As Byte()
    Private _person As Person

    Private Sub CreateDB_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CreateDB.Click
        Using entities = New EFConcurrencyTestContext
            Dim personEntity As New Person With {.FirstName = "AAA"}
            entities.People.Add(personEntity)
            entities.SaveChanges()
        End Using
    End Sub

    Private Sub Get1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Get1.Click
        Using entities = New EFConcurrencyTestContext
            Dim personEntity = entities.People.Where(Function(p) p.ID = 1).FirstOrDefault
            _fName = personEntity.FirstName
            _rowVersion = personEntity.RowVersion
            _person = personEntity
        End Using
    End Sub

    Private Sub TestConcurrencyWrongWayButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TestConcurrencyWrongWayButton.Click
        Using entities = New EFConcurrencyTestContext
            Try
                Dim personEntity = entities.People.Where(Function(p) p.ID = 1).FirstOrDefault
                personEntity.FirstName = "CCC"
                personEntity.RowVersion = _rowVersion
                entities.SaveChanges()
            Catch concurrencyException As DbUpdateConcurrencyException
                Throw New Exception("The record u r trying to update has changed")
            Catch ex As Exception
                Throw New Exception("Some Exception")

            End Try

        End Using
    End Sub

    Private Sub TestConcurrencyRightWayButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TestConcurrencyRightWayButton.Click
        Using entities = New EFConcurrencyTestContext
            Try
                Dim personEntity = entities.People.Where(Function(p) p.ID = 1).FirstOrDefault
                personEntity.FirstName = "CCC"
                entities.Entry(personEntity).Property("RowVersion").OriginalValue = _rowVersion
                entities.SaveChanges()
            Catch concurrencyException As DbUpdateConcurrencyException
                Throw New Exception("The record u r trying to update has changed")
            Catch ex As Exception
                Throw New Exception("Some Exception")
            End Try

        End Using
    End Sub

    Private Sub TestConcurrencyWithAttachButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TestConcurrencyWithAttachButton.Click
        Using entities = New EFConcurrencyTestContext
            Try
                _person.FirstName = "xxxx"
               entities.Entry(_person).State = EntityState.Modified
                entities.SaveChanges()
            Catch concurrencyException As DbUpdateConcurrencyException
                Throw New Exception("The record u r trying to update has changed")
            Catch ex As Exception
                Throw New Exception("Some Exception")
            End Try
        End Using
    End Sub

    Private Sub ModifiedRepositoryWithOriginalRowVersionButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ModifiedRepositoryWithOriginalRowVersionButton.Click
        Dim _repository As New TestRepository(New EFConcurrencyTestContext)
        Try
            Dim personEntity = _repository.GetQuery(Of Person).Where(Function(p) p.ID = 1).FirstOrDefault
            personEntity.FirstName = "CCC"
           _repository.SetRowVersion(Of Person)(personEntity, _rowVersion)
            _repository.Save()
        Catch concurrencyException As DbUpdateConcurrencyException
            Throw New Exception("The record u r trying to update has changed")
        Catch ex As Exception
            Throw New Exception("Some Exception")

        End Try
    End Sub
End Class

image

Test Case 1
1.    Click Get 1 – Person data is got from the database and stored in memory
       a.    Person.FirstName = A
       b.    Person.RowVersion = 1
2.    Update the Person Table FirstName = B, the row version will be 2
3.    Click TestConcurrencyWorngWay, Update happens no concurrency exception

Test Case 2
Repeat 1 and 2 as in Test Case1, Click TestConcurrencyRightWay. No Update, concurrency exception is raised

Test Case 3

You can also get the concurrency exception to work by doing attach, but you got to store the person entity in memory to attach it to the context. In multi tier MVC application if you are using View model to carry data to the controller, then this becomes a problem as you need to store the domain object in memory. But to test it repeat 1 and 2 as in test case 1 and then click TestConcurrencyWith Attach, no update happens concurrency exception occurs

Test Case 4

Sometime you may be using repository pattern in your application, to test this repeat 1 and 2 as in test case 1, and then click ModifiedRepositoryWithOriginalRowVersion. Below is a sample repository

Imports System.Data.Entity
Imports System.Data.Entity.Design.PluralizationServices
Imports System.Globalization
Imports System.Data.Entity.Infrastructure

Public Class TestRepository
    Private _context As DbContext
    Private ReadOnly _pluralizer As PluralizationService = PluralizationService.CreateService(CultureInfo.GetCultureInfo("en"))
    Public Sub New(ByVal context As DbContext)
        If context Is Nothing Then
            Throw New ArgumentNullException("context")
        End If
        Me._context = context
    End Sub

    Private Function GetEntityName(Of TEntity As Class)() As String
        Return String.Format("{0}.{1}", DirectCast(_context, IObjectContextAdapter).ObjectContext.DefaultContainerName, _pluralizer.Pluralize(GetType(TEntity).Name))
    End Function

    Public Sub Save()
        _context.SaveChanges()
    End Sub

    Public Sub SetRowVersion(Of TEntity As Class)(ByVal entity As TEntity, ByVal originalRowVersion As Byte())
       _context.Entry(entity).Property("RowVersion").OriginalValue = originalRowVersion
    End Sub

    Public Function GetQuery(Of TEntity As Class)() As IQueryable(Of TEntity)
        Dim entityName = GetEntityName(Of TEntity)()
        Return DirectCast(_context, IObjectContextAdapter).ObjectContext.CreateQuery(Of TEntity)(entityName)
    End Function
End Class

EF 4.1 Code First Disable checking for EdmMetadata table

When you use code first, EF will generate the database for you based on your class. Subsequently when you make changes to the classes EF is smart enough to detect the changes and warn you to regenerate the database or it regenerates the database for you based on your setting. You can achieve this by using Database.Setinitializer in the system.data.entity namespace.

image

You have two options
1.    Drop Create Database Always or
2.    Drop Create Database If Model Changes

EF creates a table EdmMetadata in your database, creates a hash of your entities and then every time you run the application it compares the hash to see if there were changes to the model. Behind the scene you will see the below sql being run first.

SELECT   TOP ( 1 ) [Extent1].[Id]        AS [Id],
[Extent1].[ModelHash] AS [ModelHash]
FROM     [dbo].[EdmMetadata] AS [Extent1]
ORDER BY [Extent1].[Id] DESC

This works well for your initial development, but after you have the core database ready and development as started you could generally want to avoid this, or if your scenario is Code first with existing database then you would avoid this.

Let us assume you started with an existing database and code first, or you started with code first and then deleted EdmMetadata as it serves no purpose. When you run the application an exception will occur behind the scene which will not be obvious in your application, because EF does not care if EdmMetadata is there are not. If it is not there it assumes you are tracking the changes and you are in-charge, so it ignores the exceptions. You can see this by using EF Profiler

image

image

The way to avoid this exception and let EF know we are in-charge of the Metadata is to add the below line in the your OnModelCreating Method

Protected Overrides Sub OnModelCreating(ByVal modelBuilder As DbModelBuilder)

‘To disable checking for EdmMetadata table.
modelBuilder.Conventions.Remove(Of IncludeMetadataConvention)()

Wire IIS7 Basic Authentication to Authenticate against custom provider

The best custom basic authentication out there is at http://custombasicauth.codeplex.com/

But many people have told me that they don’t want to write iis extensions modules etc. So here is the simplest one, just implement ihttpmodlue

1.    Create a class library project called it Company.HttpModules
2.    I add the a class called RevBasicAuthenticationModule
3.    Below is the Code for the class

Imports System.Web
Imports System.Security.Principal
Imports System.Text

Public Class RevBasicAuthenticationModule
Implements IHttpModule

Public Sub Dispose() Implements System.Web.IHttpModule.Dispose

End Sub

Public Sub Init(ByVal context As System.Web.HttpApplication) Implements System.Web.IHttpModule.Init
AddHandler context.AuthenticateRequest, AddressOf OnEnter
End Sub

Private Sub OnEnter(ByVal sender As Object, ByVal e As EventArgs)
Dim application As HttpApplication = DirectCast(sender, HttpApplication)
If Not Authenticate(application.Context) Then
application.Context.Response.Status = “401 Unauthorized”
application.Context.Response.StatusCode = 401
application.Context.Response.AddHeader(“WWW-Authenticate”, “Basic realm=My Company”)
application.CompleteRequest()
End If
End Sub

Public Shared Function Authenticate(ByVal context As HttpContext) As Boolean
‘Enable this if you are using ssl. Which you should
‘If Not HttpContext.Current.Request.IsSecureConnection Then
‘    Return False
‘End If

If Not HttpContext.Current.Request.Headers.AllKeys.Contains(“Authorization”) Then
Return False
End If

Dim authorizationHeader As String = HttpContext.Current.Request.Headers(“Authorization”)

Dim principal As IPrincipal = Nothing
If GetPrincipal(authorizationHeader, principal) Then
HttpContext.Current.User = principal
Return True
End If
Return False
End Function

Private Shared Function GetPrincipal(ByVal authorizationHeader As String, ByVal principal As IPrincipal) As Boolean
Dim credentials = GetAuthorizationHeader(authorizationHeader)
If credentials IsNot Nothing AndAlso ValidateUser(credentials, principal) Then
Return True
End If

principal = Nothing
Return False
End Function

Private Shared Function GetAuthorizationHeader(ByVal authorizationHeaderInfo As String) As String()
‘Get Header info.
If authorizationHeaderInfo Is Nothing OrElse authorizationHeaderInfo.Length = 0 OrElse Not authorizationHeaderInfo.StartsWith(“Basic”) Then
Return Nothing
End If

‘ The Credentials are seperated by ‘:’ and are Base64 encoded
Dim EncodedCredentials As String = authorizationHeaderInfo.Substring(6)
Dim credentials As String() = Encoding.ASCII.GetString(Convert.FromBase64String(EncodedCredentials)).Split(New Char() {“:”c})

If credentials.Length <> 2 OrElse String.IsNullOrEmpty(credentials(0)) OrElse String.IsNullOrEmpty(credentials(0)) Then
Return Nothing
End If

Return credentials
End Function

Private Shared Function ValidateUser(ByVal creds As String(), ByVal principal As IPrincipal) As Boolean
If creds(0) = “Rev” AndAlso creds(1) = “Rev” Then
principal = New GenericPrincipal(New GenericIdentity(“Rev”), New String() {“Administrator”, “User”})
Return True
ElseIf creds(0) = “Ram” AndAlso creds(1) = “Ram” Then
principal = New GenericPrincipal(New GenericIdentity(“Ram”), New String() {“User”})
Return True
Else
principal = Nothing
Return False
End If
End Function

End Class

4.    Added a empty asp.net website to the solution

5.    Add reference to the Company.httpModules

6.    Edit web.config

<system.webServer>
<modules>
<add name=”Company.httpModules” type=”Company.httpModules.RevBasicAuthenticationModule”/>
</modules>
<security>
<authorization>
<add accessType=”Allow” users=”” roles=””/>
</authorization>
</security>-
</system.webServer>

7.    Important make sure Anonymous Authentication is enabled and the rest are disabled for that application

image

8.    That is it you have a successful custom basic authentication. You can implement your own validate user how you want.
9.    But remember the authentication will take place for every request. So you have to use a mechanism to create a token or  cache credentials
10.    In the Custom Basic Authentication code on codeplex created by Dominick Baier has a cache mechanism which is good and can be used here

Custom Basic Authentication for IIS7

Installing and Using Custom Basic Authentication for IIS7.
1.    Download the code from http://custombasicauth.codeplex.com/.
2.    Open visual studio command prompt by right clicking run as administrator.
3.    Cd to the folder where you unzipped the downloaded source.
4.    In the output folder there is Install command file. Edit this file in notepad.
5.    Remove “rem” from line 16 rem iisschema.exe /install CustomBasicAuthentication_schema.xml.
6.    Remove “rem” from line 20 i.e rem IisRegMgmt CustomBasicAuth LeastPrivilege.CustomBasicAuthentication.Management.CustomBasicAuthenticationModuleProvider LeastPrivilege.CustomBasicAuthentication.Management.dll
7.    Save the file
8.    Run Install.cmd from VS cmd prompt

What happens when you run the install.cmd
1.    The 3 dlls will be added to the GAC
2.    When the command “iisschema.exe /install CustomBasicAuthentication_schema.xml” is executed 2 things happen.
•    CustomBasicAuthentication_schema will be copied to C:\Windows\System32\inetsrv\config\schema folder
•    <section name=”customBasicAuthentication” overrideModeDefault=”Allow” allowDefinition=”Everywhere” /> will be added to
<sectionGroup name=”system.webServer”>
<sectionGroup name=”security”>
<sectionGroup name=”authentication”>
Section in applicationHost.config file
3.    When IisRegMgmt is run it edit administration.config file.
a.    <add name=”CustomBasicAuth” type=”LeastPrivilege.CustomBasicAuthentication.Management.CustomBasicAuthenticationModuleProvider, LeastPrivilege.CustomBasicAuthentication.Management, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f20dc168dfd54966″ />  to the  </moduleProviders>

b.    To    <location path=”.”><modules><add name=”CustomBasicAuth” /></modules>

4.    Open an application in inetmgr. Double click Authentication

image

5.    You should see Custom Basic Authentication

How to use it

1.    Create an empty asp.net website.
2.    Edit web.config, Add
<system.webServer>
<validation validateIntegratedModeConfiguration=”false”/>
<modules>
<remove name=”ScriptModule”/>
<add name=”ScriptModule” preCondition=”managedHandler” type=”System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35″/>
<add name=”CustomBasicAuthentication” type=”LeastPrivilege.CustomBasicAuthentication.CustomBasicAuthenticationModule, LeastPrivilege.CustomBasicAuthenticationModule, Version=1.0.0.0, Culture=neutral, PublicKeyToken=F20DC168DFD54966″/>
</modules>
To System.webserver,modules section
3.    Add
<security>
<authentication>
<customBasicAuthentication enabled=”true” realm=”Your Company Name” providerName=”default” cachingEnabled=”true” cachingDuration=”15″ requireSSL=”false”/>
</authentication>
</security>
</system.webServer>
4.    You will need to hook up your custom provider. To Test I created a class library project. Called Company.Security.Provider. Added a class calledMemberProvider.vb
5.    Add refrence to system.web
6.    In the class Imports System.Web
7.    And Inherits System.Web.Security.MembershipProvider

image

8.    The only method I implement was ValidateUser
Public Overrides Function ValidateUser(ByVal username As String, ByVal password As String) As Boolean
If username = “rev” And password = “rev” Then
Return True
Else
Return False
End If
End Function
9.    Here I intend to hook up to my active directory module
10.    In the web project add reference to this class library.
11.    Edit the web.config file, add the default  provider in system.web section

<system.web>
<membership defaultProvider=”Company.Security.Provider”>
<providers>
<clear/>
<add name=”Company.Security.Provider” type=”Company.Security.Provider.MemberProvider”/>
</providers>
</membership>

12.    That’s it, you have custom basic authentication working