Mark Needham

Thoughts on Software Development

Archive for the ‘asp.net mvc’ tag

ASP.NET MVC: Pre-compiling views when using SafeEncodingCSharpCodeProvider

with 2 comments

We’ve been doing some work to get our views in ASP.NET MVC to be pre-compiled which allows us to see any errors in them at compilation rather than at run time.

It’s relatively simple to do. You just need to add the following code into your .csproj file anywhere below the element:

<Target Name="AfterBuild">
    <AspNetCompiler VirtualPath="/" PhysicalPath="$(ProjectDir)\..\$(ProjectName)"/>
</Target>

where VirtualPath refers to the virtual path defined inside your project file and PhysicalPath is the path to the folder which contains the project with the views in.

As I previously mentioned we’re using Steve Sanderson’s SafeEncodingHelper to protect our website from cross scripting attacks.

A problem we ran into when trying to pre-compile these views is that when the AfterBuild target gets run it tries to compile our views using the SafeEncodingCSharpCodeProvider, leading to this error:

 [msbuild] /global.asax(1): error ASPPARSE: The CodeDom provider type "SafeEncodingHelper.SafeEncodingCSharpCodeProvider, SafeEncodingHelper" could not belocated. (\path\to\web.config line 143)

From what we could tell it looked like the AspNetCompiler was expecting the dll containing SafeEncodingCSharpCodeProvider to be within the directory we specified for the PhysicalPath but we were actually compiling it to another directory instead.

	<target name="compile">
		<msbuild project="solutionFile.sln">
			<property name="OutputPath" value="/some/output/path" />
		</msbuild>
	</target>

We only noticed this on our build machine because when Visual Studio builds the solution it builds each project into ProjectName/bin which meant that locally we always had the dll available since we rarely do ‘Project Clean’ from the IDE.

The solution/hack to our problem was to build just that project in Nant without specifying an OutputPath – by default msbuild builds into the /bin directory of the project which is exactly what we need! Our compile target now looks like this:

	<target name="compile">
		<msbuild project="projectWithViewsIn.csproj">
		</msbuild>
		<msbuild project="solutionFile.sln">
			<property name="OutputPath" value="/some/output/path" />
		</msbuild>
	</target>

It’s not the greatest solution ever but it’s an easier one than changing how we use the compilation path throughout the build file.

Written by Mark Needham

March 24th, 2009 at 10:55 pm

Posted in .NET

Tagged with

ASP.NET MVC: Reducing duplication for partial models

with 3 comments

One of the problems we can encounter when using partials throughout our views is how we should create the model needed for those partials.

The approach that we have been following is to have the partial/child model on the parent model and then just call the appropriate method where we create the partial.

e.g.

public class ParentModel 
{
	public string Property1 {get;set;}
	public ChildModel ChildModel { get;set; }
}
 
public class ChildModel
{
	public string Property1 {get;set;}
}

We have sometimes run into the problem where the data in the ChildModel is being populated from the ParentModel (due to it also being needed there) leading to data duplication.

1
2
3
4
5
6
ParentModel parentModel = new ParentModel();
parentModel.Property1 = "value1"
parentModel.ChildModel = new ChildModel 
						{	
							Property1 = parentModel.Property1;
					  	}

Now the other problem with this is that we are relying on line 2 being executed before line 3 – we have created an order dependency in our code for no gain!

We are following a convention of having minimal logic in our views which means that we want to avoid creating the ChildModel in our view, meaning that we now have a problem to solve.

A cool approach which Dave introduced me to makes use of the Adaptor pattern to solve the problem.

We would adjust the ParentModel like so:

public class ParentModel
{
	public IChildModel { get { return new ChildModelAdaptor(this); }}
}

We then just delegate the calls to the ParentModel and drive the ChildModel to become an interface since it no longer needs to be a class.

public interface ChildModel
{
	string Property1 {get;set;}
}
public class ChildModelAdaptor : IChildModel 
{
	private ParentModel parentModel;
 
	public ChildModelAdaptor(ParentModel parentModel)
	{
		this.parentModel = parentModel;
	}
 
	public string Property1
	{		
		get { return parentModel.Property1; }
	}
}

If the data on the ChildModel is completely independent of the ParentModel then I would probably just create the model like before.

If the data on the ChildModel is a combination of data from the ParentModel and other classes then I would pass in those other classes in the constructor of the adaptor.

Written by Mark Needham

March 3rd, 2009 at 11:55 pm

Posted in .NET

Tagged with ,

ASP.NET MVC: Driving partials by convention

with 4 comments

I like to have conventions in the code I write – I find it makes the code i write much cleaner which still providing flexibility.

One of the conventions that Jeremy Miller coined for working with ASP.NET MVC applications is that of using one model per controller method aka “The Thunderdome principle”. I think we can take this further by having one model per partial that we use inside our views.

The benefit of having a model especially for a partial is that we remove confusion about data available to populate our controls by restricting the amount of data we actually have. It also makes more sense from a conceptual point of view.

Given this approach it started to become quite annoying having to type the following code all the time.

<% Html.RenderPartial("_Foo", new FooModel()); %>

We realised that a neater approach would be if we could just pass in the model and it would work out which partial needed to be rendered, assuming the convention that each model is only used on one partial.

We are using strongly typed models on our views so the code behind in each of the partials extends ViewPage, making it possible to work out the partial we want to load by looking up the model.

public static class HtmlHelperExtensions
{
    public static void RenderPartialFrom(this HtmlHelper htmlHelper,  object model)
    {
        var thePartial = FindMeThePartial(model);
        htmlHelper.RenderPartial(thePartial, model);
    }
 
    private static string FindMeThePartial<T>(T model) where T : class
    {
        var projectAssembly = Assembly.Load("Project");
        var types = projectAssembly.GetTypes();
 
        foreach (var type in types)
        {
            if (type.BaseType == typeof(ViewPage<T>))
            {
                return type.Name;
            }
        }
        return string.Empty;
    }
}

You can then refer to this in views like so:

<% Html.RenderPartialFrom(new FooModel()); %>

Obviously it takes the first result it finds, so the convention we have is that each model should only be used on one partial which I think is a reasonable idea.

Written by Mark Needham

February 21st, 2009 at 10:39 am

Posted in .NET

Tagged with