Friday, 16 August 2013

Login failed. The login is from an untrusted domain and cannot be used with Windows authentication.

I started getting this message, seemingly randomly, when running my integration tests.

The integration tests were using EF 5.0 to connect to my local SQL Server instance.

A lot of the blogs on this error are focused on how to resolve this issue given that you are connecting to a SQL Server instance on another machine, another domain - in which the error and its message seems relevant.

However, given that I was connecting locally, I couldn't make sense of it.

I then realised that VS2012 had created an App.Debug.config and App.Release.config in addition to the App.config file I was editing.

I was alternating running the tests in Release and Debug modes to see if that alone was causing the problem, but the error occurred in both modes.

To try and isolate the problem, I removed the EF connection string from all app.configs in the Testing project.

Then ran the tests in Debug mode - as expected it complained that the connection string was missing.

So I put it back in - exactly as it was previously.

And the error went away - WTF???

There was some talk of this error being caused by cached credentials - this would imply that at some stage, my windows login was cached and that the Test Runner is using that to login to SQL Server - but that shouldn't be a problem because its the same account I use to login via SQL Server Manager anway...

So I have no idea what has caused the problem...nor a reliable solution to make it go away.

It did happen again though - same project - but different code base version; I simply deleted the connection string from the App.Debug.config file, ran the tests, it complained about missing connection string, I added it back just as it was...and VOILA - the 'Login failed' error doesn't occur and the tests run as per normal...

Monday, 31 December 2012

MVC Best Practice Questions

As I'm developing, I often ask myself: "what is the best way to do XYZ".

Here are a list of questions I've asked myself which I hope to have answered:

1. How best to deal with Enum values which are passed to the Repository by a Controller?
Option - encapsulate the Enum type within the Data layer and make the Repository method accept a string which it then attempts to convert to an Enum value.
Con: The Repository method is not type safe in that any old string can be passed in.
Pro: The consumer (i.e. an MVC Controller) does not have to know about the Enum type - it can pass in what ever string it has to hand (i.e. passed as an action parameter).
Question: In this scenario, how does one deal with Errors whereby the Repository get passed a string which does not parse successfully into an Enum value - does the Repository throw an exception and then its up to the Controller to catch the Exception and handle it? This has a definite code smell to it...

Thursday, 27 December 2012

Creating Custom RemoteAttributes to ensure IsValid() calls the correct validation method

In a previous post i noted that the IsValid() method of the System.Web.Mvc.RemoteAttribute class simply returns true.

It makes much more sense to have the IsValid() method actually invoke the method specified in the 'HttpMethod' property i.e. the method configured to be called from the client to perform the remote validation...however, by calling it within IsValid(), then the validation routine will be performed on the server as part of the default model binding.

The objective is to be able to simply check ModelState.IsValid() within a Controller Action and know that whatever validation method you specify in the RemoteAttribute declaration is called.

The code for the custom remote attribute:

Temp Link to another solution

Will ModelState.IsValid consider properties with RemoteAttribute data annotations?

Yes and... No.

The default model binder will call the IsValid() method of the RemoteAttribute class.

However, this method simply returns the value 'true'.

This is why it seems that the Model validation is simply ignoring any RemoteAttribute properties on your Models...

I personally was hoping that the IsValid() method of the RemoteAttribute class would be clever enough to call the method specified in the HttpMethod property which handles the validation.

To make this happen, there are a couple of options I have found:

1. Make your model implement the IValidatableObject interface. Information about this can be found in this article:
Exercise 3: Using IValidatableObject Custom Validation
and on this StackOverflow post:
ModelState.IsValid vs IValidateableObject in MVC3

2. Create a custom validation attribute which inherits from the RemoteAttribute and override the IsValid() method to call the correct validation procedure. Information on this technique can be found in my post here:
Creating Custom Remote Attributes

Wednesday, 18 July 2012

MVCMusicStore with SQL Server 2008

This is what i did to get the ASP.Net xxx example project to work with SQL Server 2008:


1. Created new Database MVCMUSICSTORE
2. Ran script as is with the exception of removing the USE xxx data store reference
3. Database created successfully
4. Changed DB Connection string to:

  <connectionStrings>
    <add name="MusicStoreEntities"
     connectionString="Data Source=WEAPONX\BEAST;Initial Catalog=MVCMUSICSTORE;Integrated Security=True"
     providerName="System.Data.SqlClient"/>
  </connectionStrings>

5. Ran the solution...Got this error:
Model compatibility cannot be checked because the database does not contain model metadata. Ensure that IncludeMetadataConvention has been added to the DbModelBuilder conventions.
6. Followed the steps in this post: http://mvcmusicstore.codeplex.com/discussions/317690/
7. Ran the solution...Got this error:
An error occurred while executing the command definition. See the inner exception for details.
INNER EXCEPTION: {"Invalid object name 'dbo.Album'."}
8. After reading a post about how this message can sometimes come about when EF is expecting pluralized Entities and the tables are not pluralized (or vice versa) I looked at the offending line of code:

            return storeDB.Albums
                .OrderByDescending(a => a.OrderDetails.Count())
                .Take(count)
                .ToList();

- comparing that to the table name 'dbo.Album', it seems my solution required EF to pluralize the entities
- so i removed the modifications to MusicStoreEntities.cs as stipulated in the step 6.

9. Ran the solution...it works - lovely jubely!

Thursday, 8 March 2012

jQuery UI Custom Tabs - Issues & Notes

* had to change to 'bind' to get it to work more than once.

* mouseexit doesn't seem to exist

* the problem with his 'selected tab' solution is that it requires a unique action name for each tab

consider a simple site which has various controllers, each with an Index action which is the first View to return for each section rendered by a tab

so instead, the convention needs to change...

at first i tried to change it to controller-actiontab but then this breaks as soon as you load a view resulting from a call to a different action within that controller

luckily, the site works on the convention that a single controller is in charge of all the views rendered for a particular tab, so should be able to change the convention to use controller name by itself

also the use of 'find' is troublesome since it will find EVERY 'ul' element and 'li' element within the
container 'div' and apply the styles to it.

this is a problem since we've chosen to render the body of each view within the menu containing div:

<div id="tabs" >
    <ul id="menu">
        <li id="ControllerTab">@Html.ActionLink("Link Text", "ActionName", "ControllerName")</li>       
    </ul>           
       
    <section id="main">
        @RenderBody()
    </section>
</div>

what you need to do is restrict the application of styles to 'ul' element's with the ID 'tabmenu'

Wednesday, 22 February 2012

How Does System.Web.MVC.AuthorizeAttribute work???

[Authorize]
public ActionResult AuthenticatedUsers()
{
 return View();
}

[Authorize(Users = "Betty, Johnny")]
public ActionResult SpecificUserOnly()
{
 return View();
}

[Authorize(Roles = "Admin, Super User")]
public ActionResult AdministratorsOnly()
{
 return View();
}


How Does System.Web.MVC.AuthorizeAttribute work???

The inner-workings of the Authorize Attribute are a mystery to all developers bar those that have taken the time to research what the hell its doing under the hood - developers like yourself, presumably, since you're reading this!

This attribute works by looking at HttpContext.User.

First, it checks to see if

HttpContext.User.Identity.IsAuthenticated == true


If you've provided specific User names to authenticate, like this

[Authorize(Users = "Betty, Johnny")]
Then it will ensure the user name property of the current request (HttpContext.User.Identity.Name), matches one of the names you provided (case insensative).

Finally, if you've provided specific Roles, like this

[Authorize(Roles = "Admin, Super User")]

Then the application calls

HttpContext.User.IsInRole(yourRolesHere)

How Does HttpContext.User get set?

The answer depends on whether your application is using Forms or Windows authentication.

This article explains the ASP.Net Security Architecture - a MUST READ for any serious ASP.Net developer!

Forms Authentication

If you're using FormsAuthentication (as opposed to Windows Authentication, for example), the FormsAuthenticationModule will handle the forms authentication control flow as part of the ASP.Net Request Processing Pipeline.

The FormsAuthenticationModule authenticates the user by inspecting the forms authentication ticket, which is typically included in the user's cookies collection. If no forms authentication ticket is present, the user is anonymous and not authenticated (see: source).

Note that in Windows authentication scenarios, when the user is not authenticated, the HTTP 401 status is returned to the browser. This status code causes the browser to prompt the user for their credentials via a modal dialog box.

With FormsAuthentication, however, the HTTP 401 Unauthorized status is never sent to the browser. Instead, the FormsAuthenticationModule detects the HTTP 401 status and modifies it to redirect the user to the login page (as configured in the <authentication> section of the web.config) via an HTTP 302 Redirect status.

The user will then submit their logon credentials via the HTML Form. The credentials are then authenticated against a data store; typically a Microsoft SQL Server database or Microsoft Active Directory directory service.

If the credentials are authenticated, then the FormsAuthenticationModule issues an Authentication Ticket to the browser (via a cookie or in the URL) and redirects the browser to the original URL specified in the QueryString as the RETURNURL variable (which was set by the FormsAuthenticationModule when it detected the HTTP 401 status).

Now that the user has a valid FormsAuthentication ticket, HttpContext.User.Identity.IsAuthenticated will be set to true!

AND the HttpContext.User property will be set to the IPrinciple instance the FormsAuthenticationModule created during the authentication process.

Note that the authenication ticket can be automatically generated (as described above) or explicitly generated - by using FormsAuthentication.SetAuthCookie.

Windows Authentication

Using Windows Authentication however enables the user to be authenticated (i.e. IsAuthenticated is set to true) automatically via their domain account and therefore the HttpContext.Current.Request user is set to that of the remote clients Windows user account.

Windows Authentication is implemented in ASP.NET using the WindowsAuthenticationModule module. The module constructs a WindowsIdentity based on the credentials supplied by IIS and sets the identity as the current User property value for the application.

IIS supplies these credentials via a number of authentication mechanisms, including anonymous authentication, Windows integrated (NTLM) authentication, Windows integrated (Kerberos) authentication, Basic (base64 encoded) authentication, Digest authentication, and authentication based on client certificates.

See What Identity does IIS return to an ASP.NET application for more information about IIS authentication.

Click the following link for more information about IIS Authentication Mechanisms.