Tigraine

Daniel Hoelbling-Inzko talks about programming

Rant: Interface violation inside ASP.NET MVC

Posted by Daniel Hölbling on May 27, 2009

I’m amazed about how bad the ASP.NET MVC code really is. Why? Because something as trivial as redirecting the output of a View to another TextWriter shouldn’t take more than 5 lines of code and certainly not be impossible!

But from the start, here’s the scenario. ViewResult should not be written to HttpContext.Response but to some arbitrary TextWriter.
So, for me the most obvious choice was to alter the ViewResult to write to somewhere else. So redirecting should be as easy as:

public ActionResult Index()
{
    ViewData["Message"] = "Welcome to ASP.NET MVC!";
    TextWriter writer = Console.Out;
    return new RoutedViewResult(writer);
}

Now, nothing left to do but override the ExecuteResult method and call View.Render() with another writer:

image

So, what do you see here? A method that takes a ViewContext (containing ViewData, TempData, HttpContext etc..) and a TextWriter. 
Any normal person would now jump to the conclusion, that if I build a ViewContext and pass in my TextWriter, I’m set and all is well.

So, I spent almost 30 minutes trying to find a way on how to construct the ViewContext (without copy/pasting the code from within the framework, btw. forget it – they married ViewContext creation with View rendering, so no way to separate those) just to find out that my output was still written to HttpContext.Response.

That’s when I looked at the WebFormView class that implements the IView interface, but does so badly.
Let me explain:

public interface IView
{
    // Methods
    void Render(ViewContext viewContext, TextWriter writer);
}

The interface clearly states that there should be a TextWriter passed to the View.
Imagine my face when I saw the implementation in the WebFormView class:

public virtual void Render(ViewContext viewContext, TextWriter writer)
{
    if (viewContext == null)
    {
        throw new ArgumentNullException("viewContext");
    }
    object obj2 = this.BuildManager.CreateInstanceFromVirtualPath(this.ViewPath, typeof(object));
    if (obj2 == null)
    {
        throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, MvcResources.WebFormViewEngine_ViewCouldNotBeCreated, new object[] { this.ViewPath }));
    }
    ViewPage page = obj2 as ViewPage;
    if (page != null)
    {
        this.RenderViewPage(viewContext, page);
    }
    else
    {
        ViewUserControl control = obj2 as ViewUserControl;
        if (control == null)
        {
            throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, MvcResources.WebFormViewEngine_WrongViewBase, new object[] { this.ViewPath }));
        }
        this.RenderViewUserControl(viewContext, control);
    }
}

Do you see the problem? Writer is NEVER used. They violate their own interface in their own code. What a mess.

Something similar has been done with the EmailTemplateService in MVCContrib, but it’s very email specific and works with using a MemoryStream as filter to the HttpContext.Response (not happy with that either, but apparently the only way).

Filed under net, programmierung
comments powered by Disqus

My Photography business

Projects

dynamic css for .NET

Archives

more