Integrating ASP.NET MVC into an existing ASP.NET Webforms application

If, like me you’re not always blessed with the opportunity to build every application from scratch, you may find yourself wanting to introduce the wholesome goodness of ASP.NET MVC into an existing ‘classic’ ASP.NET Webforms application. Most tutorials out there concentrate on nice green field development.

What follows is largely a reference for me to remember how to do this.  It’s basically a matter of manually injecting what the project templates do for a new application.  I’m also not professing to have come up with all of these steps – I’m just bringing them together.

I’ll assume you’ve got all the necessary prerequisites (MVC 4.0) installed already, and if you have a web ‘site’ project, then I’d suggest you update it to a web application before doing all of this.

Getting the structure and configuration to look like MVC

There’s a number of standard folders, and bits of code you’ll find dotted around MVC applications – Models/Views/Controller for instance :)

The following article goes through the first steps of getting those folders into your project (assuming you don’t have a naming conflict).

Mixing ASP.NET WebForms and ASP.NET MVC

Updating to MVC4

This is all good, but that article’s a bit old, and you’ll find the next one brings you (mostly) up to date with MVC 4.0

Adding MVC 4.0 to WebForms Project

If you want to use any of the newer features such as bundling, or if you’ve copied some views from an MVC4 project into your new MVC project, you’ll need the ASP.NET Web Optimization Framework (get it from NuGet).

You may also want to take an MVC4 project and convert the global.asax code to call off to the classes in the App_Start folder…

    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            AuthConfig.RegisterAuth();
        }
    }

Getting the Visual Studio MVC Template Goodness

This is great, but the icing on the cake is to make Visual Studio think this is an MVC project, so you get the nice right-click options, like add–>Controller if you’re in the controllers folder.  It turns out you just need to fool Visual Studio by adding a project type guid in your web projects csproj file…

With Visual Studio I just did a quick diff between a new MVC 4 project’s project file, and my ‘hybrid’ project’s file.

The following is what you’re looking for…


<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{18BBC72C-702B-40CD-B347-D7FC66D276FA}</ProjectGuid>
<ProjectTypeGuids>{E3E379DF-F4C6-4180-9B81-6769533ABE47};{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}</ProjectTypeGuids>

If you just add the first ‘ProjectTypeGuids’ guid to the corresponding place in your project file, and reload, the magic happens, and Visual Studio thinks it’s now an MVC project.  You’ll probably find you already had the other 2 guids.

Use SQL Server Trusted Connections with ASP.NET on Windows 2003 without impersonation

Access control and troubleshooting 401 errors must be one of the most annoying and recurring issues with configuring IIS.  One of the problems is that it’s often quite a long time between issues, and you simply forget how you solved something last time.  This time I decided to write it all down as I set things up.

Target Scenario
My target scenario is a local intranet, where you want to use a ‘service account’ to access SQL Server, directly from your ‘trusted’ web application, removing the need for impersonation. 

The benefits of this are of course that you can take advantage of connection pooling, but also removing the need to configure passwords in web.config for SQL users (or specific, impersonated domain users).  This also removed the overhead of configuring specific domain users and their SQL Server permissions.  It may also be that you just want to simplify your security model to work only on Windows authentication across the stack.  

SQL Server

  1. Create a new role in the database you’re accessing, for the purposes of your application
  2. Add your service domain user account to the role in SQL Server
  3. Assign permissions to objects, stored procedures etc to the role (not directly to the user)

IIS/Web Site

  1. Set up your web site/application as you would normally – one way to do things….
    1. Create your web application root folder on the web server
    2. Copy your files (or use your deployment tools/scripts to do this)
    3. Create a new application pool to house your new web application (probably model this from the default web site).  This is important as this is where the credentials will be set
    4. Create the new IIS web application against the root folder (if not already done as part of step 2)
    5. Associate the new IIS application with the new application pool
    6. Set the ASP.NET version of your IIS application appropriate (may need to restart IIS here)
  2. Ensure ‘Integrated Security’ is set ON in the Directory Security tab, and ‘Anonymous’ access is switched OFF
  3. Set the application pool’s ‘identity’ to the domain user you want to run the application (and connect to SQL Server) as
  4. Open a command window and Go to the windows\Microsoft.NET\Framework\vXXXXX folder
    1. run aspnet_regiis -ga <domain>\<user> to grant necessary access to the metabase etc for the service account (as per http://msdn.microsoft.com/en-us/library/ff647396.aspx#paght000008_step3 )
    2. In the command window go to the inetpub\adminscripts folder, and set
      NTAuthenticationHeaders metabase property as per instructions at
      http://support.microsoft.com/kb/326985.  you can also use MetaEdit from
      the IIS Resource Kit to change this.  If you’re fully configured to use Kerberos then you can potentially skip this step, as it’s all about making IIS use NTLM authentication.
  5. Navigate to ‘Web Service Extensions’ in IIS Manager, and ensure that the ASP.NET version you’re targeting is ‘allowed’.  e.g. ASP.NET 4.0 is ‘prohibited’ by default.

Summary
So here we’ve circumvented the need to use impersonation by running the ASP.NET application as a specific domain user that is configured as a SQL Server Login, and granted the right access by means of a SQL Server role.  The main work is the plumbing to get IIS to work happily with that user in standard NTLM authentication (you may be able to use Kerberos depending on your network configuration).

Other background on creating service accounts can be found at http://msdn.microsoft.com/en-us/library/ms998297.aspx

Using JQuery with DotNetNuke 4.x

I’m currently doing a project using DotNetNuke, and we’re using JQuery plugins to achieve certain content rotation and scroller functionality.  All was ‘amost’ good as I’d found a way to inject the JQuery script to the page header on a per-skin basis, but in ‘edit’ mode the actions button wasn’t showing up at the top of containers in FireFox and was causing JavaScript errors in IE.

I’d already gone through the hoops of declaring jQuery.noConflict(), but it still appeared to be conflicting with the dnn:actions (solpartactions) control.  I’d read somewhere else about Solpart code being incompatible with JQuery.

I tried one last thing, adding the noConflict() call in the JQuery library script file itself – rather than running as a fragment on page load.  This fixed everything, as something else was obviously getting in and hijacking in the meantime.  Apparently with V5 this will all be fixed as JQuery’s more integrated with the framework.  Anyway, for those interested here’s what I had to do to get JQuery (and associated plugins) talking nicely whilst still allowing the actions menu to pop up on my containers…

  1. Amend the JQuery library (jquery.1.x.x.min.js) by adding the following line at the bottom…

    jQuery.noConflict();

  2. Amend the skin you want to load the jquery library (and plugins) in (we’ve got it only in specific skins to avoid the overhead where it’s not required).  You could also do this in the module by checking ‘if loaded’, but here’s the code for a skin (in ascx file)…

    <script runat=”server”>
        Private Sub Page_Init(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Init
            ‘add a script reference for Javascript to the head section
            AddScript(“/js/jquery.scrollable-1.0.2.min.js”)
            AddScript(“/js/jquery.mousewheel.js”)
            AddScript(“/js/jquery-1.3.2.min.js”)
        End Sub
       
        Private Sub AddScript(ByVal fileName As String)
            Dim oLink As New HtmlGenericControl(“script”)
            oLink.Attributes(“language”) = “javascript”
            oLink.Attributes(“type”) = “text/javascript”
            oLink.Attributes(“src”) = fileName
            Dim oCSS As Control = Me.Page.FindControl(“CSS”)
            If Not oCSS Is Nothing Then
                oCSS.Controls.AddAt(0, oLink)
            End If
        End Sub
    </script>

    The order is important, as we’re adding the scripts to the ‘top’ of the scripts each time.  JQuery needs to be the first referenced.

  3. Make sure that anywhere you use jQuery you use the jQuery(xx) syntax, and not $(xx).

That’s it.

ASP.NET Data Binding – Accessing a parent data item from within a nested repeater

I’m maintaining an app at the moment that uses quite a few nested repeaters, and found that headers were being output when there was no data present.  It was found that the header was being written in the ItemTemplate of an ‘outer’ repeater, rather than as the HeaderTemplate of the ‘inner’ repeater.  The next problem was how to reference the outer repeater from the ‘inner’ HeaderTemplate…

The following will bind to a field called HeaderDescription.

<%# DataBinder.Eval(Container.Parent.Parent, “DataItem.HeaderDescription”) %>

The parent of the inner item is it’s repeater, so you have to go to it’s parent to get the right RepeaterItem.  Why don’t you just do the following you ask?

<%# DataBinder.Eval(Container.Parent.Parent.DataItem, “HeaderDescription”) %>

..’cos it doesn’t work – The Eval method expects a ‘Control’ as its first parameter.  There’s other ways to do this server-side, but the first option is probably the easiest.

To complete the picture and only show when there’s data you can add the following to the ‘inner’ repeater declaration

OnItemDataBound=”ItemDataBound” Visible=”false”

then..

        protected void ItemDataBound(object sender, RepeaterItemEventArgs e)
        {
            if (e.Item.ItemType == ListItemType.Item)
            {
                if (!e.Item.Parent.Visible)
                    e.Item.Parent.Visible = true;
            }

        }

This will ensure that you’ll only show if you’ve bound a ‘data’ item (remember you’re doing binding in the HeaderTemplate too).  You could also hook similar things into other events, but it’s generally more convenient to put these things into events that relate to the actual control (pre_render’s probably another good candidate as it will only get called once and you can check the count in the DataSource).

Technorati Profile

Removing references to HttpModules from ASP.NET SubFolders in web.config

If you have ASP.NET applications that live as subfolders of a larger site, you may find yourself with issues when it tries to find assemblies and httpmodules that are referenced in the parent’s web.config.

Fortunately this is something you can work around.  Matthew Nolton goes through how you ‘remove’ these references at the subfolder level using the <remove> element.

This is all fine until you get an even tastier situation like I encountered the other day…

ASP.NET application ‘A’ lives as subfolder ‘B’ of both parent site ‘C’ and ‘D’.  The configuration of ‘C’ and ‘D’ is slightly different (modules, handlers, assemblies etc).  Why is this a problem you ask?  We were trying to be a bit clever (and failed :) ) by only deploying application ‘A’ once.  Virtual directories in site ‘C’ and ‘D’ both point to the same physical ‘A’ folder.  This effectively means that the stuff that needs to be removed from ‘A’ varies depending on which parent site you’re accessing.

OK – I could just fix this by duplicating the installation, and varying the configuration but….

You can also remove all modules by adding a ‘clear’ element as follows…

<httpModules>
    

<clear/>

</httpModules>

This is fine, BUT if you’re using Session State or any other in-built features that are implemented as httpModules then you’ll get exceptions as ASP.NET will give you a ‘null’ session for instance.

The following is probably a safe list of modules you’d normally need (maybe even only the session for simple apps), so just add them back in after the ‘clear’….

<httpModules>
    
<clear/>
    
<add name=”OutputCache” type=”System.Web.Caching.OutputCacheModule”/>
    
<add name=”Session” type=”System.Web.SessionState.SessionStateModule”/>
    
<add name=”WindowsAuthentication” type=”System.Web.Security.WindowsAuthenticationModule”/>
    
<add name=”FileAuthorization” type=”System.Web.Security.FileAuthorizationModule”/>
</httpModules>

This is nicer for a couple of reasons

  1. It shows what dependencies the application has on ASP.NET/external features, and…
  2. It gives you the power back to have the application consumed by multiple sites as you’ve effectively decoupled yourself from the parent’s dependencies.

Invalid Postback or Callback Argument – ASP.NET. One cause

Just been getting this error.  It’s quite common, especially if you’re using Ajax.  I got the error for an altogether more ‘schoolboy error’ reason.


I had a textbox control e.g. called ‘customerName’, and two radio buttons controlling whether to show the customer name.  These had a ‘GroupName’ of customerName, and this caused the error.  You need the GroupName to associate the radio buttons together, but the postback mechanism obviously sees that as the control identifier.  Silly boy. 


The naming was pretty bad in any case and actually prompted me to take more of a long hard look at the UI to tidy it up so no such conflict would arise.

ASP.NET – The name xxx does not exist in the current context

I recently converted a Web Site to a Web Application project, and as it had been a while I tripped up on a few things. 

First of all I made the mistake of creating a new Web Application and pasting all the web files in there (I was intending to split some of the site into another Class Library), and I wanted to port to another file structure.  I mistakenly thought it would be easier to do this ‘before’ changing to the WAP.

I then of course got a gazillion compiler errors (well – 1436 to be exact) on the new project.  The vast majority of which were ‘The name xxx does not exist in the current context’.  Yes it does! (I protested).  Well.  That showed mistake number 2.

If you want to convert then use the ‘Convert to Web Application’ option on the Web Site properties (or on the individual pages if necessary).  This does a number of things:

  1. Sorts out your project structure
  2. Changes ‘CodeFile’ to ‘CodeBehind’ and other directives
  3. Adds a designer file for pages and controls
  4. Other stuff that you shouldn’t bother yourself with etc…

The compiler errors were due to the fact that the WAP model expects pages to be structured in a certain way, and although the ‘code’ looks fine (and Resharper was green all the way) it won’t compile ‘cos the designer files are missing and hence so are the definitions the compiler’s looking for.

See Steven Smith’s post on some other tips for converting projects.

Getting the most out of ASP.NET Web Deployment Projects

In my ongoing love (but mostly) hate relationship with ASP.NET Web ‘Site’s’ I’ve been using Web Deployment projects to make things more bearable. 


I currently swap in connection strings from 3 files – one for each build configuration (debug, test, release – connectionstrings.debug.config etc ).  This works fine as per the doco on WDP.  I use CruiseControl.NET and NAnt to automate builds, and a few nagging ‘automated’ pieces were missing from the puzzle. 



  1. Encryption of connectionStrings (or other web.config sections that you want to protect) – without affecting the ‘source’ file.  I’ve assumed here that ‘internal’ people are trusted. 
  2. Changing of other config stuff (like debug=false) in the test and release builds.  (My attempts to get this to work had previously failed as you don’t seem to be able to specify system.web as a replaceable section.
  3. Encrypting Forms authentication passwords, using MD5 hash.  This isn’t difficult, I just didn’t have a tool to generate the hash value.

Encryption of config sections


OK – after re-reading Scott Gu’s post on Web Deployment Projects, and K. Scott Allen’s post on how to simply encrypt sections of config files, I realised that I could just add a post-build event (manually) in the wdproj file (right-click in solution explorer –> open project file). 


The build events are already in but commented at the bottom of the file.  I ended up with

<Target Name=”AfterBuild”>
<Exec WorkingDirectory=”$(OutputPath)” 
Command=”C:\windows\Microsoft.NET\Framework\v2.0.50727\aspnet_regiis -pef connectionStrings .”
/>
<!– Also remove our ‘source’ config files using the del command rather than the delete task as you
have to jump through hoops to specify wildcards –>
<Exec WorkingDirectory=”$(OutputPath)” Command=”del compilation*.config” />
<Exec WorkingDirectory=”$(OutputPath)” Command=”del connectionstrings*.config” />

</Target>


If I put this anywhere other than ‘AfterBuild’ it didn’t seem to do anything.  I certainly learnt a bit more about aspnet_regiis, as I’d only used it previously to ‘install’ ASP.NET.  I also had to specify the path to aspnet_regiis, but you could obviously use a property for this (I’m new to MSBuild – only dipping in when I have to, so the framework path may already be a standard property?).


Replacement of system.web sections


The key thing here (which I don’t believe was documented very well anywhere) is how to replace system.web elements.  Other typical replacements – e.g. appSettings or connectionStrings are children of the root config element.  You’d therefore assume that you need to replace the whole of system.web (which is a little inconvenient – but still worth it).  This doesn’t work and you’ll get a ‘nice’ WDP00002 error saying it can’t find the system.web element (a bit like saying ‘can’t find printer’ when it’s right next to the computer!). 


You just have to go one level down as follows (in the Deployment –> Web.config file section replacements property page):


system.web/compilation=compilation.release.config


compilation.release.config may be as simple as…

<compilation debug=”false”></compilation>

You might have a warning saying ‘compilation’ isn’t a valid element, but this is just the intellisense barking as it validates against the config schema.


Encrypting Forms Authentication Passwords


This is pretty simple and there’s lots of docs to support this, but I wanted a simple tool to generate the hash for a given string, and a quick google yielded a nice little command-line tool


This way you can plug it into your build if you need to, but also replace for different environments using the techniques above.


ASP.NET Web Site Project (WSP) vs Web Application Project (WAP)

ASP.NET 2.0 originally came without support for the ‘traditional’ Web Application project that everyone had become familiar with in ASP.NET 1/1.1.  Some people liked the new approach as it affords more ‘on-the-fly’ updates, but obviously enough people ‘didn’t’ for Microsoft to release a patch for Visual Studio .NET 2005 to allow creation of WAP’s.  The support was then formally re-added in VS 2005 SP1 (making the original patch redundant).


Info on the situation can be found here.


This post (as well as saving the links for me) is also a reminder of the limitations of the Web ‘Site’ model (hereafter known as WSP) and why I choose not to use it.



  • Namespaces.  WSP does not explicitly add a namespace to any page, class etc.  It uses ‘special folders’ with some implied names (e.g. App_Code) to determine the namespace hierarchy.  This whole situation can also lead to strange ‘circular reference’ errors with user controls – especially after converting from VS 2003.  At the very least you’ll be pulling your hair out wondering why you can’t reference some page or control from somewhere else in your site.
  • Code Reuse.  Only code in the App_Code folder (and below) can actually be referenced by another class in the project.  This forces a structure that you wouldn’t otherwise choose.  You can of course create separate assemblies – and should in many cases.
  • Unit Testing support in VS 2005.  WSP does not build to a single assembly when built in VS 2005, and must be ‘precompiled’ using a Web Deployment Project which in turn uses the asp_merge (publish) utility in order to achieve this.  The standard publish function doesn’t support a single assembly, although it’s possible to get the App_Code into a single DLL. This all means that because you don’t have an output at build time, you can’t run unit tests in the WSP – regardless of how much code you’re ‘reusing’ in the App_Code project.  You can jump through some hoops to call the NUnit Console runner, but why bother!?   
  • Included/Excluded files.  Because WSP doesn’t have the concept of a project file to say what’s ‘in’ and what’s ‘out’, VS 2005 uses a rather nasty ‘rename’ method of excluding files – simply suffixing the file with .exclude to denote it should be disregarded.
  • References are actually just copied in.  If you create a reference to an external assembly, VS 2005 will actually just copy the file into your bin folder.  This means you’ll end up putting all sorts of binaries in your source tree (under source control), that you maybe otherwise wouldn’t
  • Automated Build.  NAnt and other automated build tools can’t work out whether a Web Site project is some sort of ‘enterprise template’ project, or a tub of lard – because it’s not really a project.  This means that you can’t use the <solution> task with NAnt.  you have to call a custom <exec> task instead, calling the asp_merge.exe tool, then call all other projects separately too.  This all works, but again, why bother?  A cynic might conclude MS was trying to cause issues for NAnt, whilst getting people interested in MSBuild.

For me, any change that introduces new ‘non-standard’ tools, just so you can have the convenience of ‘on-the-fly’ updates just isn’t worth it.  You’ll actually find that this all goes out the window when you deploy to a server anyway, because depending on how you ran asp_merge, you probably won’t be able to do any ‘real’ updates because the assembly names are generated in that process and you’ll break the site by changing source files.  In my opinion if you are using this approach then use the Web Deployment project and build to a single assembly to minimse these issues.  If you’ve got any sort of structure around your production deployments (and you can’t just ‘copy over’) then I see literally no advantage in the WSP model, as it just seems to provide too much pain for no visible gain.

ASP.NET Open Source Content Management Systems – The Winner

Well, it’s been a little while since I first talked about Content Management Systems, but I can declare that


mojoPortal is the one for me.


There’s a number of reasons, but I’ll go through the main pro’s than means it wins out over DotNetNuke



  1. It’s XHtml compliant out of the box, and has minimal use of tables.  All the people producing skins for MojoPortal are also well evolved along the accessibility curve too.

  2. It uses standard .NET features.  This is due in no small part I’m sure to the fact that it started after DNN and more facilities were around in ASP.NET at the time.  This means that Skins, Themes, Master pages are all present and correct with MojoPortal, rather than the proprietary (but well documented) skins in DNN.

  3. It seems to be quick(er than DNN)

  4. The facilities are stable and work very nicely.  There are less modules, but the developer video tutorials are a really good way to get yourself into developing your own modules and edit pages.

  5. You can get involved and work with the code – after downloading from SVN (I fixed a small bug and felt really good about it!)

  6. Finally – and this is an easy clincher – the support for the product is just fantastic.  Joe Audette is like a man possessed on the forums, and you’re likely to get a really well thought out answer to any query within a few hours (depending on the time zone!).  He’s sorted me out on a few occasions and set me along the righteous path. 

In summary, mojoPortal is something I’m happy to be using for a client as I’m more keen to use standard .NET features than proprietary skinning.  I also like the philosophy more of the development community, and how Joe Audette’s running the project