Best asp.net-mvc-3 questions in March 2011

How to use ASP.NET MVC 3 and Stackoverflow's Markdown.

11 votes

I've been researching for a few hours now and couldn't find any real sources for this. I'm building a site in ASP.NET MVC 3 and would like to take advantage of the Markdown editor that StackOverflow uses. Does anybody have a good tutorial?

Where do you download the latest markdown? What language is it written in? Where would I start in integrating this into an MVC 3 project? Even after all the searching and reading I've done I'm still pretty confused.

I came across one site. http://daringfireball.net/projects/markdown/ But this seems outlandishly old and it would seem I would have to learn a little something about CGI and PERL which I have absolutely no experience with. A javascript/jQuery version would be splendid. Any ideas, links, references are much much much appreciated.

UPDATE

I noticed this question is getting a fair amount of views so I decided to update it with some helpful references. I managed to get a Markdown editor working nicely on CodeTunnel.com and I wrote a few blogs about it. Hopefully they help anyone who comes across this question.

Stackoverflow open sourced their version of Markdown to the world. Its called MarkdownSharp and is written in C#.

Somebody wrote a HtmlHelper here: http://blog.dantup.com/2011/03/an-asp-net-mvc-htmlhelper-extension-method-for-markdown-using-markdownsharp

If you are looking for how to implement a javascript editor there is an existing question: Integrate Markitup text editor to ASP.NET MVC project

How to tell why an IIS application pool is recycled

7 votes

Background:

I've deployed an ASP.NET MVC 3 app that works on my machine to a shared hosting provider and am discovering some problems that appear to be related to the application pool being recycled. The host has configured recycling to occur under any of these circumstances:

  • Memory usage exceeds 200MB
  • CPU usage exceeds 75% (presumably over a sustained period)
  • 20 minutes of idle time

The restrictions are more relaxed on my development machine so I wasn't seeing recycling like this during development. I don't have admin access to the shared hosting box (understandably) so I can't read the event log to see why this recycling is occurring.

Question:

Is there a way I can find out why my app was recycled (in Application_End for example) so that I can log it to help my debugging?

Research - 1

Firstly I tried using System.Web.ProcessModelInfo.GetCurrentProcessInfo() and System.Web.ProcessModelInfo.GetHistory(int). The results of these methods return info such as the PID, start time, age, status, and peak memory usage. Unfortunately these were unavailable in my hosting environment:

HttpException 0x80004005 - Process metrics are available only when the ASP.NET process model is enabled. When running on versions of IIS 6 or newer in worker process isolation mode, this feature is not supported.

This approach might work for others though, so if you're in this situation, give it a shot.

Research - 2

The property System.Web.Hosting.HostingEnvironment.ShutdownReason is an enum with lots of values, but unfortunately all the cases I outline in my question are bundled into a single enum value:

ApplicationShutdownReason.HostingEnvironment: The hosting environment shut down the application domain.

Research - 3

ScottGu has an approach on his blog (which is the same code Kev posted) that uses reflection to access internal state of the HttpApplication. Unfortunately in this case it only reports the same detail as #2 above:

_shutDownMessage =
  HostingEnvironment initiated shutdown
  HostingEnvironment caused shutdown

_shutDownStack =
  at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)
  at System.Environment.get_StackTrace()
  at System.Web.Hosting.HostingEnvironment.InitiateShutdownInternal()
  at System.Web.Hosting.HostingEnvironment.InitiateShutdownWithoutDemand()
  at System.Web.Hosting.PipelineRuntime.StopProcessing()

MVC 3 Dependency Resolver or Ninject MVC plugin?

6 votes

In MVC 3 they added a Dependency Resolver what I been using. While answering someone question someone commented on you should use the Ninject MVC 3 plugin.

So my question is why use it over the built in one? If it is the way to go how do you setup it up?

Question

So above is the link to the question that I answered.

The Ninject.Web.MVC extension (or Ninject.MVC3 NuGet package) use a dependency resolver internally too. So basically it is using the same mechanism. But there are several reasons to use the extension rather than implementing an own dependency resolver:

  1. Why implementing an own dependency resolver when there's already an extension doing exactly the same? Using the same implementation than others makes it much easier to support you when you have a problem. Furthermore the more using the same implementation the more stable it gets. (See point 4).
  2. The extension is more than just a dependency resolver. See http://www.planetgeek.ch/2010/11/13/official-ninject-mvc-extension-gets-support-for-mvc3/ for a list of all features that come with the extension.
  3. It adds support for fast deactivation of objects InRequestScope after the request ends by default. This prevents that applications with a heavy load run into an OutOfMemory exception.
  4. The dependency resolver in your post and the one above both have a problem. In some situations under heavy load your application will crash and only display yellow pages of death until the application is restarted. I don't like to answers all the question that will come in future only because a faulty dependency resolver is used. Add at least a .ToList() to the GetServices
  5. Support for InRequestScope will be removed in Ninject 2.4 to remove the dependency to System.Web to reduce the number of build targets. This is a breaking change. But projects based on one of the Web extensions will only need a very minimalistic change to get it running again. InRequestScope will still be available to projects using one of these extensions. Custom implementations will have to add support themselves.

How to create a default AjaxOptions for Razor Views?

6 votes

How do I create a default AjaxOptions? For example, I have a menu with some links, I want to make the entire website to use the same loading element and same error handling.

@Ajax.ActionLink("Home", "Index", "home", <AjaxOptions>)

new AjaxOptions()
{
    OnFailure = "handleError",
    LoadingElementId = "loading"
});

But then I have some links that update the content and I want to set UpdateTargetId for each of those links. How can I keep a default error handling and loading element on all the views and edit only UpdateTargetId or OnSuccess (or another property) for each link?

Something like

@Ajax.ActionLink("home", "Index", "home", ajaxOption.UpdateTargetId = "content")
@Ajax.ActionLink("menu", "Foo", "home", ajaxOption.UpdateTargetId = "side-content")

I want something equivalent to jQuery.setup where I can set the default values to ajax requests and when I make an ajax request I only tell the parameters I want to override...

You could do something like:

public static class AjaxExtensions
{
    public static IHtmlString DefaultLink(this AjaxHelper helper, string text,
        string action, string controller, string updateTargetId = "", 
        string onSuccess = "")
    {
        // Build your link here eventually using 
        // the arguments passed
        var options = new AjaxOptions
        {
            OnSuccess = onSuccess,
            UpdateTargetId = updateTargetId,
            OnFailure = "handleError",
            LoadingElementId = "loading"
            // etc...
        }

        // return a normal ActionLink passing your options
        return helper.ActionLink(text, action, controller, options);
    }
}

Note I'm using optional parameters in the signature to benefit from the flexibility of multiple overloads without the nuisance of maintaining them. Expand as needed :)

Then just use it as follows:

@Ajax.DefaultLink("home", "Index", "home", updateTargetId: "content")

WatiN best practices/rules of thumb for an ASP.NET MVC app

5 votes

Hi everyone,

I'm an avid TDD and BDD fan but haven't done much in the ways of UI testing. I have an ASP.NET MVC 3 application with many MSpec tests and I'd like to add presentation tests using WatiN.

What sort of stuff do you test? Do I have to write tests for the initial load of the UI or only for things that changed due to user interaction?

What are, in short, good rules of thumb and best practices when writing WatiN (and UI tests in general) tests?

Where I work now, we test these 5 things (where applicable) for each page:

  1. Layout - should have textbox labeled X, should have dropdown labeled X
  2. Populate - should have dropdown with the following values ... should have textbox with the value
  3. Validate - when I enter X, then I should see the error message Y
  4. Navigate - when I click X button, then I should go to Y page
  5. Save - when I click save button, then I should see the Success message

Handling required fields in ASP.NET MVC when using Entity Framework

5 votes

Ok, this problem is really getting under my skin. Let me start out by describing my app in a step by step format.

First I have my Entity Framework generated model. Within it I have the following entities:

Now, to implement validation on an entity, I use partial classes and handle the OnChanging hooks that EF provides. Here is a sample of the PostComment partial class:

namespace CodeTunnel.Domain.Models
{
    public partial class PostComment : IDataErrorInfo
    {
        private Dictionary<string, string> _errors = new Dictionary<string, string>();

        partial void OnAuthorChanging(string value)
        {
            //Validating anything but required value works fine.
            //Like this pseudo-validator.
            if (value.ToLower() != "fred")
                _errors.Add("Author", "Sorry, your name must be Fred.");
        }

        partial void OnBodyChanging(string value)
        {
            //Required value validation does not work, I will tell you why below.
            if (string.IsNullOrEmpty(value))
                _errors.Add("Body", "Body is required.");
        }

        #region -= IDataErrorInfo methods =-

        public string Error
        {
            get { return string.Empty; }
        }

        public string this[string columnName]
        {
            get
            {
                if (_errors.ContainsKey(columnName))
                    return _errors[columnName];
                return string.Empty;
            }
        }

        #endregion
    }
}

Notice that my class inherits from IDataErrorInfo. MVC checks this for validation errors by default. If it finds any then it invalidates the model and uses the stored errors as the messages for the validation helpers in the view. I'm pretty sure when EF throws an exception, this dictionary never even gets populated with a value for that property. In fact, I'm not even sure that MVC goes so far as to look for a value after detecting and invalidating the model upon the EF generated exception.

Here is a screen shot of the problem, including the sample pseudo-validator so you can see it is working:

As you can see, the error message didn't show up. However, it did correctly validate the field as invalid. If I put a value in there then it validates just fine. I've done A LOT of research on this issue and here is what I know:

The reason you cannot customize the error message that is displayed for required fields is because the model property is not nullable. Because it is not nullable, trying to bind a null value to it throws an exception. MVC swallows this excepion and invalidates the model as it should. The message is generated wherever this exception occurs. I don't know if the message is generated by EF or MVC (I'm guessing MVC since it was responsible for swallowing the exception in the first place). I don't know how to customize this message. As you can see it always says "The value '' is invalid." which I suppose isn't totally horrible but it's really not very user-friendly.

It gets to my name validator and checks if your name is "fred" just fine because no exception is thrown. As far as EF is concerned the value passed in is fine. It isn't until it gets to my OnAuthorChanging method that it realizes it's not okay. This is the correct behavior and works just fine.

If I throw an exception in my OnChanging events instead of adding to my IDataErrorInfo dictionary I can generate the same validation message, only it puts the entered value between the single quotes. Example:

    partial void OnAuthorChanging(string value)
    {
        if (value.ToLower() != "fred")
            //_errors.Add("Author", "Sorry, your name must be Fred.");
            throw new Exception("Sorry, your name must be Fred.");
    }

That code shows this message when "test" is entered as the value for Author: "The value 'test' is invalid.". With the required fields it's just that the value is null so there is nothing to put between the single quotes.

Several people (like this guy) suggest that you simply set the property to nullable in your model. This is NOT an acceptable solution. One reason why not is this:

Error 3031: Problem in mapping fragments starting at line 313:Non-nullable column PostComments.Body in table PostComments is mapped to a nullable entity property.

Also, setting nullable simply will not work on non-nullable types such as int, and switching int to a nullable int is a yucky mess that I won't even get into here.

The bottom line is, I want to handle those exceptions from EF myself or at the very least customize the message it generates but I don't know how. I'm completely lost. All I want to do is customize a message on what I thought was very simple model validation!

Any help is much appreciated.

MVC is validating your model based on the type being non nullible, as you have discovered. This is adding errors to ModelState before your custom validation runs.

I had this before, and got round it by looping through Modelstate at the start of an action and removing everything, then doing my custom validation (bad!!)

Then found even if you are not using data annotations as your main form of validation, you can customise the message that is thrown by adding [Required to the non nullible type in the buddy class, and specify the message.

It's something like this:

[MetadataType(typeof(YourClassMetadata))]
public partial class YourClass
{       
     //buddyclass to entity class
    class YourClassMetadata {
     [Required(ErrorMessage="Your custom overriding error message")]
     public int NonNullablePropertyThatIsGivingYouProblems {get;set;}
    }
}

I've started to look at fluent validation (http://fluentvalidation.codeplex.com) for mvc, and they seem to turn off the problem in global.asax, in on application_start() by adding the line

DataAnnotationsModelValidatorProvider .AddImplicitRequiredAttributeForValueTypes = false;

but I may be wrong about that.

MVC3: WebGrid Column Format Issue

5 votes

I've been trying to change the format of a single column in a WebGrid without much success.

Said column is this:

grid.Column(columnName: "EmailAddress", header: "Email Address", format:(item) => Html.EmailLink(item.EmailAddress, item.EmailAddress, ""), canSort: false),

The error is:

The best overloaded method match for 'System.Web.Helpers.WebGrid.Column(string, string, System.Func, string, bool)' has some invalid arguments

I am confused as the method signature matches. Also, if I change the column to:

grid.Column(columnName: "EmailAddress", header: "Email Address", format:(item) => new HtmlString(String.Format("<a href=\"mailto:{0}\" class=\"{2}\">{1}</a>", item.EmailAddress, item.EmailAddress, "")), canSort: false),

It works without error.

For reference, EmailLink is a very basic HtmlHelper extension method:

    public static IHtmlString EmailLink(this HtmlHelper helper, string emailAddress, string linkText, string linkClass) {
        return new HtmlString(String.Format("<a href=\"mailto:{0}\" class=\"{2}\">{1}</a>", emailAddress, linkText, linkClass));
    }

Apologies if I've missed any detail - this is my first post eek

This is due to the ugliness of WebGrid and all this dynamic crap. You need a cast:

grid.Column(
    columnName: "EmailAddress", 
    header: "Email Address", 
    format: item => Html.EmailLink(
        (string)item.EmailAddress, 
        (string)item.EmailAddress, 
        ""
    ), 
    canSort: false
)

This being said don't hesitate to checkout MvcContrib Grid or the Telerik Grid which are far better.

Why does mvccontrib's AssertViewRendered().ForView("Edit") fail due to view name being full cshtml path?

5 votes

I have the following unit test:

    [TestMethod]
    public void Add_Returns_Edit_View()
    {
        // Act
        ActionResult result = _controller.Add();

        // Verify
        result.AssertViewRendered().ForView("Edit");
    }

This should be passing, since the Add action is returning the Edit view. However, this assertion fails with the following exception

MvcContrib.TestHelper.ActionResultAssertionException: Expected view name 'Edit', actual was '~/Views/JobSearch/Edit.cshtml'

Why is the view name coming back as the full path name? Could this be due to my usage of T4MVC, and if so how can I get this to pass?


Edit The Add view looks like this:

    public virtual ActionResult Add()
    {
        return View(MVC.JobSearch.Views.Edit, new JobSearch());
    }

You can test against the T4MVC value like this :

result.AssertViewRendered().ForView(MVC.JobSearch.Views.Edit);

I think it's the cleaner solution... If you have better let me know :)