First line empty in Razor

First of all, I never thought a problem so simple would give me such a hard time!

My Problem

I’m using Razor views to generate some XML. I know I should probably use some sort of Serializer/Deserializer for that kind of job, but I needed something easier to change and preferably something that doesn’t need to be compiled. The problem is an empty line before my content which off course makes it invalid.

The code looks like:

@{
Response.ContentType = "text/xml";
}
<?xml version="1.0" encoding="UTF-8" ?>
...

and here is how the output is generated:

Empty line before content

First Try

The first thing I tried was to move the <xml> tag to the line above getting rid of the new lines that could possibly have.

@{
Response.ContentType = "text/xml";
}<?xml version="1.1" encoding="UTF-8" ?>
...

I even moved the Razor block to the bottom…

<?xml version="1.1" encoding="UTF-8" ?>
...
@{
Response.ContentType = "text/xml";
}

Nothing!

Second Try

Ok. This first line is not in my code. Something is putting it there. No problem! I can create a Response Filter and change the output removing this empty line.

using System.IO;
using System.Text;
using System.Web.Mvc;

namespace MyWebsite.Helpers
{
    public class RemoveEmptyLineWriter : MemoryStream
    {
        private readonly Stream filter;

        public RemoveEmptyLineWriter(Stream filter)
        {
            this.filter = filter;
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            var content = Encoding.UTF8.GetString(buffer);
            content = RemoveFirstEmptyLine(content);
            filter.Write(Encoding.UTF8.GetBytes(content), offset, Encoding.UTF8.GetByteCount(content));
        }

        private static string RemoveFirstEmptyLine(string content)
        {
            var firstLineIsEmpty = content.Substring(0, 2) == "\r\n";
            return firstLineIsEmpty ? content.Substring(2, content.Length - 2) : content;
        }
    }

    public class EmptyLinesRemoverFilter : ActionFilterAttribute
    {
        public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            base.OnResultExecuted(filterContext);
            var response = filterContext.HttpContext.Response;
            response.Filter = new RemoveEmptyLineWriter(response.Filter);
        }
    }
}

 

[EmptyLinesRemoverFilter]
public ActionResult Index()
{
  return View();
}

This code I found here, and then I changed it a little bit.

It simply adds to the Response a Filter which is invoked after the output is generated. So I can get it, modify and write again to the buffer.

I think this would have worked just fine if it wasn’t for my IIS being configured to Gzip the document. With Gzip enabled, after I read the buffer the content is just a bunch of messy characters. Decompressing the content and then compressing again is not a solution as it would cause an unnecessary overhead in my application. I’d rather turn Gzip off for those type of files but only if I really had to.

I also tried changing the order that my filter is added by changing the OnResultExecuted to OnActionExecuting but it doesn’t affect the order that the filter is executed, only the order in which it’s added to the response, which makes no difference.

My next try would be creating an IHttpModule, but I wanted something easier and something that I didn’t have to intercept all my requests.

Solution 1

Maybe you were lucky and the previous solutions worked for you, but in case they don’t, here is what worked for me. I had to go deeper in MVC and change the hierarchy of which the rendering is executed.

I ended up with this:

using System.Web.Mvc;
using System.Web.WebPages;

namespace MyWebsite.Helpers
{
    public class RazorXmlViewPage<T> : WebViewPage<T>
    {
        public override void ExecutePageHierarchy()
        {
            Response.ContentType = "text/xml";
            Layout = null;
            PushContext(new WebPageContext(), Response.Output); // push a new page context to the stack
            base.ExecutePageHierarchy();
        }

        public override void Execute()
        {

        }
    }

    public class RazorXmlViewPage : RazorXmlViewPage<object>
    {

    }
}

and in my Razor view…

@inherits RazorXmlViewPage<IEnumerable<string>>
<?xml version="1.0" encoding="UTF-8"?>

Thanks to this post that provided a source code that helped me get to this one.

The Razor view file inherits the WebViewPage by default. This page tells Razor that it inherits from a different class, in which I can override the execution of its core methods. We also have to override the Execute method because it is abstract.

It turns out I din’t even have to modify the output. Just by pushing a new WebPageContext to the stack the page rendered without the blank line.

But, if wanted, I could do some cools things with the Output. Take this code for instance:

public override void ExecutePageHierarchy()
{
    StringWriter writer = new StringWriter();
    PushContext(PageContext, writer);
    base.ExecutePageHierarchy();
    PopContext();

    Response.Clear();
    string output = writer.ToString();
    output = output.Replace("<body>", "<body><h1>An Example of Filtering Razor Output</h1>");
    Response.Write(output);
    Response.End();
}

If you want to understand better the methods used in the code above, take a look at the WebViewPage source code.

Solution 2

Another solution is to Render your View as a string, using the method bellow, change it and set the Response to your new content.

public string RenderRazorViewToString(string viewName, object model)
{
  ViewData.Model = model;
  using (var sw = new StringWriter())
  {
    var viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
    var viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
    viewResult.View.Render(viewContext, sw);
    viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
    return sw.GetStringBuilder().ToString();
  }
}

You know when you use return View(model);. This method it’s actually an alias to return new ViewResult {}. What the code above is doing is using the same implementation of that class, as you can see in the MVC source, in the method ExecuteResult.

I knew that I could use this code when dealing with this problem, but as I was looking at that class, I felt bad copying that much code from the MVC source and pasting it into my code. What if MVC updates as it does often and change that code? I’ll have to copy and paste it again in case this bug remains not fixed. So, for my use case I used the first solution as is less code copied and rewrote, plus, I didn’t even have to remove the first line from my output since the change skipped the bug. For other use cases the second solution might suit better your need/taste.

Please comment here what worked for you.

Shared Client and Server configuration with custom ActionResult – Solving it in a DRY way

I’m developing a MVC application and there are some configurations I want to use both on client and server side but I don’t want to replicate them, I want it be DRY (Don’t Repeat Yourself). Having it gives me the hability of changing some value on both sides without deploying the application again.

I could have created my properties in my AppSettings section and then print the variables on a page, but the AppSettings would become huge and the page header a mess.

Here is the solution I end up with. I created a JSON file containing my propeties, like so:

common.json

{
	"highlightProductId": 5,
	"bannerEnabled": false,
	"passwordLength": 15,
	"adURL": "http://google.com/ad"
}

That allows me to use the Newtonsoft or any other JavaScript parser like the JavaScriptDeserializer from .Net and have that JSON as a class. You can also deserialize it as “dynamic” if you are using the Newtonsoft library.

Well, that solves the problem for the server side. The client side though would have to call jQuery.getJSON to be able to read that file but that slows the page loading down and doesn’t give the user a nice experience because the user has to wait until the ajax call gets finished, so it can continue processing the rest of the script.

What I did was to turn that JSON into a JS file. To do that, you just have to assign that JSON to a variable and then you can embed the result in the page as a JavaScript file!

var common = { };

That is a valid JS file!

Now let’s teach MVC how to do that. Create the file below:

namespace System.Web.Mvc
{
    using System;

    public class JsonToJavaScriptResult : ActionResult
    {
        public string Prefix { get; private set; }
        public string JsonFile { get; set; }

        public JsonToJavaScriptResult(string prefix, string jsonFile)
        {
            JsonFile = jsonFile;
            Prefix = prefix;
        }

        public override void ExecuteResult(ControllerContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            HttpResponseBase response = context.HttpContext.Response;
            response.ContentType = "application/x-javascript";

            response.Write(Prefix);            
            response.WriteFile(JsonFile);
        }
    }
}

There we are creating a custom ActionResult that concatenates the prefix – which are the part that will hold our variable name – with the content of the file – our JSON – and writes it all to the page buffer.

Now let’s make our Controller that will use the newly created class.

    public class SharedController : Controller
    {        
        //
        // GET: /Shared/Script

        public JsonToJavaScriptResult Script()
        {
            const string fileName = "common.json"
            const string prefix = "var Shared = ";
            var jsonFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName);

            return new JsonToJavaScriptResult(prefix, jsonFile);
        }
    }

The last step is just insert the script tag in your page that will embed our code.

<script src="@Url.Action("Script", "Shared")" type="application/x-javascript"></script>

and you can do something like that

<script type="text/javascript">
  alert(Shared.highlightProductId);
</script>

Any new ideas or improvements are welcome.

How to Fix “HTTP Error 403.14 – Forbidden The Web server is configured to not list the contents of this directory”

This error occurs when you have MVC 2+ running hosted on IIS 7+, this is because ASP.NET 4 was not registered in IIS. In my case I was creating a MVC 3 project and hosting it on IIS 7.5.

To fix it, make sure you have MVC 2 or above and .Net Framework 4.0 installed, then run a command prompt as administrator and type the following line:

32bit (x86)

%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe -ir

64bit (x64)

%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe -ir

How to use CustomErrors in ASP.NET MVC 2

First, let’s see how our Web.config file will look like and after that I will show you how to create the pages.

<customErrors mode="On" defaultRedirect="~/Error">
  <error statusCode="404" redirect="~/Error/NotFound"/>
  <error statusCode="403" redirect="~/Error/AccessDenied"/>
</customErrors>

I’m going to show the steps to make it work for those three types of errors and also explain you about the HandleError attribute and how it handles the information specified in the customErrors. I’m also putting here the code I wrote in order to handle the AccessDenied error.

Error Page

When we are talking about the Error Page, one thing that you should understand is that without the HandleError Attribute, if an error occurs the .NET will just redirect the user to the page you specified in your Web.Config. So, if you have the “defaultRedirect” property pointing to something like “~/GenericError.aspx”, the GenericError.aspx page under the root folder of your project will be shown without any information about the Error. It could be a static HTML page that only tells the user “Hey, you’ve got an Error”.

Now, if you what you want is to show the user some information about the error, like the description or even the stackTrace but with the page looking like your default theme, then you can use the HandleError Attribute. By applying it to a Controller or a method the behavior of the customErrors changes a little bit. Instead of just pointing to some page, the exception handling will render a View, more specifically, a view called Error (if you don’t specify any other name to the Attribute) it doesn’t matter what name you’ve told the “defaultRedirect” to take you to. Along with that, it will send a HandleErrorInfo model containing the Controller name where the exception occurred, the Action name and the exception itself, so you can get the stackTrace and the description of the error.

Although it might seem obvious for some what the HandleError attribute does I’ve seen it’s a common issue people setting their customErrors to show something like GenericError.aspx and using the HandleError attribute. Or even, setting the defaultRedirect property to “Error” and expecting the Index method within the ErrorController to receive a HandleErrorInfo parameter. Remember, when using the HandleError attribute, the “Error“ View will be rendered internally, without even getting into the ErrorController.

Common mistake

Web.Config

<customErrors mode="On" defaultRedirect="Error/Ops" />

HomeController.cs

[HandleError] // using HandleError attribute
public class HomeController : Controller
{
    public ActionResult Index()
    {
		return View();
    }
}

ErrorController.cs

public class ErrorController : Controller
{
    public ActionResult Ops()
    {
        //
		// Wrong! It won't get here because
		// the HandleError will handle the error.
		return View();
    }
}

The right way

I’m going to demonstrate now how you can make it work with a page that shows some information about the error. With this example, even though someone forget using the HandleError attribute, a friendly page still shows up but without the error info (it’s better than not showing anything). It could be improved, off course, but that it’s another point.

Web.config

<customErrors mode="On" defaultRedirect="Error" />

Error.aspx

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<System.Web.Mvc.HandleErrorInfo>" %>

<asp:Content ID="errorTitle" ContentPlaceHolderID="TitleContent" runat="server">
    Error
</asp:Content>

<asp:Content ID="errorContent" ContentPlaceHolderID="MainContent" runat="server">       

    <h2>
        Sorry, an error occurred while processing your request.
    </h2>

	<% if (Model.Exception != null ) { %>
		<p>
		  Controller: <%= Model.ControllerName %>
		</p>
		<p>
		  Action: <%= Model.ActionName %>
		</p>
		<p>
		  Message: <%= Model.Exception.Message%>
		</p>
		<p>
		  Stack Trace: <%= Model.Exception.StackTrace%>
		</p>
	<% } %>
</asp:Content>

Place that page inside your Views folder. It can be either your Shared or Error folder. The name must be Error.aspx.

That’s it! Only the aspx file and the setting inside the Web.config.

Only if you want that whether the Controller have or not the HandleError attribute, your custom error page will still be shown, then you can add an action method into your ErrorController:

ErrorController.cs

public class ErrorController : Controller
{
    public ActionResult Index()
    {
		return View("Error");
    }
}

Now whether the page is being redirected to the defaultRedirect or rendered by the HandleError, the page will always be called.

To force an error, let’s create a code that throws an exception inside the Index of the HomeController:

int a = 0;
int b = 0;
int result = a / b;

That will throw the DivideByZeroException, see the friendly page in action:

CustomErrros Error Handling

 

404 NotFound Page

For the Not Found page we don’t have much to tell the user, so there is not much to do. It’s only the redirect to a page and, the information we can show is the wrong path. That information already comes as a query string.

Just to centralize the error handling and make it more organized, let’s put our NotFound within our ErrorController. So, add your the following method to the ErrorController:

public ActionResult NotFound(string aspxerrorpath)
{
	ViewData["error_path"] = aspxerrorpath;

	return View();
}

and the aspx page code:

NotFound.aspx

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>

<asp:Content ID="errorTitle" ContentPlaceHolderID="TitleContent" runat="server">
    Not Found
</asp:Content>

<asp:Content ID="errorContent" ContentPlaceHolderID="MainContent" runat="server">
    <h2>
        Sorry, the page <%: ViewData["error_path"] %> does not exist.
    </h2>    
</asp:Content>

and add the following line for the Not Found error into your customErrors section:

<customErrors mode="On" defaultRedirect="Error">
  <error statusCode="404" redirect="Error/NotFound"/>
</customErrors>

See the result:CustomError Page Not Found

 

403 AccessDenied

Most of the times when someone doesn’t have access to a page it’s only a login issue. But there are also times that a user has logged in but they are allowed to see something or perform some task, maybe because the lack of sufficient privileges. I’m going to show here how to handle those type of errors and the way I do that is by creating an ActionFilter attribute that you can put on a class or a method.

I’m going to hide some code for clarity:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Configuration;
using System.Web.Configuration;

namespace ErrorHandling.Controllers
{
    public class AuthorizationAttribute : ActionFilterAttribute, IExceptionFilter
    {
        public string Action { get; set; }
        
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            //
            // check permissions

            if (accessDenied)
            {
                throw new System.Web.HttpException((int)System.Net.HttpStatusCode.Forbidden,
                        "You are now allowed to see this page.");
            }

            base.OnActionExecuting(filterContext);
        }

        #region IExceptionFilter Members

        // this method is almost a clone of HandleErrorAttribute from MVC
        // it's just changed so that we take the error message to the page set in the <customErrors>
        public virtual void OnException(ExceptionContext filterContext)
        {
            if (filterContext == null)
            {
                throw new ArgumentNullException("filterContext");
            }
            if (filterContext.IsChildAction)
            {
                return;
            }

            // If custom errors are disabled, we need to let the normal ASP.NET exception handler
            // execute so that the user can see useful debugging information.
            if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled)
                return;

            Exception exception = filterContext.Exception;

            // If this is not an HTTP 403 (for example, if somebody throws an HTTP 500 from an action method),
            // ignore it.
            if (new HttpException(null, exception).GetHttpCode() != 403)
            {
                return;
            }

            // try to get the customError page for the 403 code
            string customErrorPage = GetCustomError("403");

            // if there isn't a redirect to a 403 error page then get out
            if (customErrorPage == null)
                return;

            filterContext.Result = new RedirectResult(String.Concat(customErrorPage, "?action=", this.Action));
            filterContext.ExceptionHandled = true;
            filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;            
        }

        #endregion

        public string GetCustomError(string statusCode)
        {
            CustomErrorsSection customErrorsSection = ConfigurationManager.GetSection("system.web/customErrors") as CustomErrorsSection;

            if (customErrorsSection != null)
            {
                CustomError customErrorPage = customErrorsSection.Errors[statusCode];

                if (customErrorPage != null)
                    return customErrorPage.Redirect;
            }
            return null;
        }        
    }
}

What that code does is throw an 403 Exception if the user rights are not enough, then we implement the IExceptionFilter, so we can handle the error on our own way with the OnException method. Notice we are reading the customErrors section looking for the page that is set for the 403 code and redirecting the user to that page.

With that AuthorizationAttribute you can decorate any class or method that you want to be checked when a user access it, like so:

[AuthorizationAttribute]
[HandleError]
public class HomeController : Controller

Let’s create our page inside the Views folder (again, it can be the Shared or the Errors folder) to tell the user about the error:

AccessDenied.aspx

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>

<asp:Content ID="errorTitle" ContentPlaceHolderID="TitleContent" runat="server">
    Access Denied
</asp:Content>

<asp:Content ID="errorContent" ContentPlaceHolderID="MainContent" runat="server">
    <h2>
        Sorry, you do not have access to the action <%: ViewData["action"] %>.
    </h2>    
</asp:Content>

Add one more action method to our ErrorController:

public ActionResult AccessDenied(string action)
{
	ViewData["action"] = action;

	return View();
}

In this example, I’m passing in a parameter called “action” to the AccessDenied method, but it could be anything you want and can contain any information you want.

And finally, completing our Web.Config, we now add the treatment for the 403 error code:

<customErrors mode="On" defaultRedirect="Error">
  <error statusCode="404" redirect="Error/NotFound"/>
  <error statusCode="403" redirect="Error/AccessDenied"/>
</customErrors>

Here is how our ErrorController end up like:

namespace ErrorHandling.Controllers
{
    public class ErrorController : Controller
    {
        public ActionResult Index()
        {
            return View("Error");
        }

        public ActionResult NotFound(string aspxerrorpath)
        {
            ViewData["error_path"] = aspxerrorpath;

            return View();
        }

        public ActionResult AccessDenied(string action)
        {
            ViewData["action"] = action;

            return View();
        }
    }
}

With this structure the errors are very organized and all the things related to it are together.

Configuring ASP.NET MVC on IIS 5 and IIS 6

I know there are other tutorials on the internet about this topic but I’m going to write here the way that worked for me.

Some tutorials I’ve seen tell you to change your Global.asax to add some routes. I didn’t have to change it at all. I only had to setup the IIS itself.

IIS 5

Configure your Virtual Directory as usual, then right click on it and select Properties. In the properties dialog, click on Configuration.  In this dialog, click on Add. Then use the settings below:

Configuring IIS 5

For Executable, use the following path:

c:\windows\microsoft.net\framework\v4.0.30319\aspnet_isapi.dll
or
c:\windows\microsoft.net\framework\v2.0.50727\aspnet_isapi.dll

depending on the version of .NET you are using on your application. You can copy the path from the other mappings that already exist.

Also make sure you uncheck the “Check that file exists” box.

Well, that is what it took for me to make it work on IIS 5.

IIS 6

For IIS 6 is not that different from what it needs on IIS 5. The process is the same until you get to the Configuration dialog. Now you add the same path showed above but the extension will change a bit. Take a look:

Configuring IIS 6

The option “Verify that file exists” must be unchecked.

After hitting OK, still in the Configuration dialog you have to add a Wildcard. Click on Insert and use the same DLL path you’ve been adding so far.

Configuring IIS 6

Once again, the option “Verify that file exists” must be unchecked – I know it’s annoying but that’s how it must be done.

See how the Configuration dialog must look like:

Configuring IIS 6

Note the extension and the wildcard added. Now, just hit OK and you’re done.

One thing I noticed is that if you name your Virtual Directory Anything.MVC it won’t work because of that “.mvc” extension you added.

Don’t worry. After doing that over and over again you get practice 😉

One good thing is that Microsoft is releasing a new Web Server called IIS Express which is as easy as the ASP.NET Development Server (that instance of Web Server that Visual Studio launches when you run a project) to configure but has almost all the features from the full version of IIS. On the new IIS Express you won’t need any extra configuration to have your ASP.NET MVC application up and running.

The new Microsoft WebMatrix – it’s like a small version of Visual Studio – already comes with the IIS Express. You can download WebMatrix here.

Firing errors with any header status code

I spent a long time trying to get it right, so I thought it would be a good idea to post this here.

Yesterday I was creating a way to validate if the user has access to some page depending on their restrictions  that comes from a security system of the company.

Great. I created a new error page to show when the user access is denied and added it in the customErros within the Web.config.

Here is how the customErros end up like:

<customErrors mode="On" defaultRedirect="GenericError.aspx">
  <error statusCode="403" redirect="Unauthorized.aspx"/>
  <error statusCode="404" redirect="NotFound.aspx"/>      
</customErrors>

As this project is being developed using MVC I decided to implement it using the ActionFilter attributes. Here is the code:

public class CustomAuthorization : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {        
        try
        {
            // check the user
        }
        catch
        {
            // set the header but doesn't show the unauthorized page.
            // can be used to Ajax though
            //filterContext.HttpContext.Response.StatusCode = (int)System.Net.HttpStatusCode.Forbidden;
            
            // redirects to GenericError
            //throw new UnauthorizedAccessException();

            // this works as excpected!
            throw new System.Web.HttpException((int)System.Net.HttpStatusCode.Forbidden, "You do not have access to that page.");
        }
        base.OnActionExecuting(filterContext);
    }
}

The last statement works the way I wanted. It fires the exception setting the header status code to 403 and redirects to my page Unathorized.aspx

I’m sure I’ve already used that HttpException before, but just to make sure I won’t forget it again, now I wrote it down.