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

Creating a Oracle Linked Server in Sql Server

1.    Make sure oracle client is installed on SQL Server machine
2.    How to test it is installed

image

3.    Make sure OraOLEDB.Oracle is listed under Server Objects\ Linked Servers\Provider

4.    Execute command EXEC sp_addlinkedserver ‘TEST_XYZ’, ‘Oracle’, ‘OraOLEDB.Oracle’, ‘XYZ_TCP’

a.    ‘TEST_XYZ’ – Name you give to the Linked Server
b.    ‘Oracle’ – Optional, just mention it
c.    ‘OraOLEDB.Oracle’ – Provider
d.    ‘XYZ_TCP’ is the name of the oracle database found in your tnsnames.ora  file

5.    After you create the linked server you need to associate a sql server login to a oracle login.

6.    Use EXEC sp_addlinkedsrvlogin ‘TEST_XYZ’, ‘FALSE’,’SqlServerLogin’, ‘OracleUserId’, ‘OraclePassword’
a.    ‘TEST_XYZ’ – Name of the Linked Server for which you want to create a remote login
b.    2nd Parameter I have mentioned as ‘FALSE’ since I did not want the current logged in user to be associated with the remote login, but wanted to have a different user in this case ‘SqlServerLogin’ to be associated. I had currently logged in using NT authentication which had amin privilages.
c.    ‘SqlServerLogin’ – SQL server login (Note: if you mention NULL then all sql server user will get access)
d.    ‘OracleUserId’ – Oracle UserId which is used to connect to oracle database
e.    ‘OraclePassword’ – Password for Oracle User

7.    How to query oracle database – select * from TEST_XYZ..OracleUserId.TABLE_NAME

8.    To disassociate the sql server user to a oracle user use EXEC sp_droplinkedsrvlogin ‘TEST_DDWT’, ‘SqlServerLogin’ (Local Login when you execute sp_helplinkedsrvlogin)

9.    To get a list of user access to linked server, use sp_helplinkedsrvlogin

Accessing File Resource on a UNC share from IIS7 running .Net 4.0 win 2008

Today we had a situation where a page was trying to load a string from another file in the UNC share.

The asp.net page looked like this

<%@ Page EnableSessionState=”False”%>

 <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”  “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd“>

 <html xmlns=”http://www.w3.org/1999/xhtml”&gt;

<head runat=”server”>

    <title></title>

</head>

<body>

    <form runat=”server”>

<div>

                 <asp:PlaceHolder runat=”server” Visible=”true”>

                    <%Response.WriteFile(“/Common/breadcrumb.htm”)%>

                </asp:PlaceHolder>

            </div>

    <div>

    My Test Page

    </div><asp:Literal runat=”server”></asp:Literal>

    <asp:Button runat=”server” Text=”test”/>

    </form>

</body>

</html>

Breadcrum.htm file just as a string. When this is executed on IIS7 in Asp.Net v2 works fine. But when run 0n IIS7 and Asp.Net v4 this generates System.UnauthorizedAccessException: Access to the path “\\unshare\common\breadcrumb.htm” is denied

Fix

<%@ Page EnableSessionState=”False”%>

<%@ Import Namespace=”System.IO” %>

<%@ Import Namespace=”System.Security.Permissions” %>

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”&gt;

<script runat=”server”>

    Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs)

        Dim oFp As FileIOPermission = New  _

        FileIOPermission(FileIOPermissionAccess.Read, Server.MapPath(“/Common/breadcrumb.htm”))

        oFp.Assert()

        Dim data As String = File.ReadAllText(Server.MapPath(“/Common/breadcrumb.htm”))

        Literal1.Text = data

    End Sub

</script>

<html xmlns=”http://www.w3.org/1999/xhtml”&gt;

<head runat=”server”>

    <title></title>

</head>

<body>

    <form runat=”server”>

    <div>

    My Test Page

    </div><asp:Literal runat=”server”></asp:Literal>

 <asp:Button ID=”Button1″ runat=”server” Text=”test” OnClick=”Button1_Click”/>

    </form>

</body>

</html>

My application pool was running under Network Services. I could have either changed the identity of the pool to use a user that had access to unc share or I could just programmatically give permission to file.  I used the FileIOPermission to grant access to the file and then read it.

Setting up Virtual Machine with Loopback Adapter

For instruction on how to install Loopback adapter check my previous post

I already had virtual hard drive, so I reattached it to create a new VM, in order to do setting

Select the VM and click settings

  • My hard drive

  • Memory

  • Networking, on the second adapter I selected Microsoft Loopback Adapter

  • I need to be able to move files between Host and VM and between VMs for that I need a Shared Folders, I also need to be able to copy past between the same. To get these things working I need first install VM Additions

  • To Install VM Additionsà start the VM in my case AD-DNS

On Action Click Install or Update Virtual Machine Additions

  • Click Continue
  • To Login into VM click the right Alt + Delete
  • Logged into VM, opened notepad typed in hello world
  • Back in the host opened Notepad and paste, hello world so copy paste was working
  • I need to set up Shared Folder
  • On the VM click

  • Click OK, Click Share Folder…
  • And select the folder on the host which you want to access and share

  • Check the Internet, click on the internet explorer in the VM, it should not work
  • Setting the loopback adapter properties in the VM
  • Open the network connection the VM

  • Check on the TCP4 properties on the Loopback adapter

  • This is because I am moving this VM from one machine to another, in order to get this to work with my Host Loopback adapter I first check my host loopback adapter.

  • So I am going to modify my VM loopback adapter to

I gave it a specific IP, and the default gateway I changed it to my Host Loopback adapter IP

  • Since this Virtual MC is my DNS I have to set the preferred DNs server to local, so it will complain when I click OK, You will not have to do this if it was a standalone no AD VM

  • Click OK
  • I went back and looked at the TCP property, preferred DNS server was blank I changed it to local host

  • Changed my other VM network adapter (LAC) properties to

  • Check the Internet, it started to work

Installing Microsoft Loopback Adapter on Windows7

  • Start -> search CMD-> right run as administrator
  • Type hdwwiz.exe

     

 

 

 

  • Under Microsoft choose Microsoft loopback adapter

 

  • After Installation my Network Connections2 looks like below

  • My LAC3 is my Loopback Adapter, I just going to rename it to Loopback

    LoopBack Adapter is used to communicate between virtual machines and in order to get internet to VM’s, you have to make internet available to Loopback adapter. So here are the set to do that

  • On my wireless Network connection, right click properties, select Sharing

  • Check “Allow other network users to connect through this computer’s Internet connection”
  • From the dropdown choose LoopBack
  • Uncheck Allow other network users to control or disable the shared internet connection

 

  • Now if you look at the TCP4 properties of the LoopBack adapter it would have got the IP address, by default it was Obtain an IP address, now