views:

4965

answers:

7

Hi. I'm using the ASP.NET 3.5 SP1 System.Web.Routing with classic WebForms, as described in http://chriscavanagh.wordpress.com/2008/04/25/systemwebrouting-with-webforms-sample/

All works fine, I have custom SEO urls and even the postback works. But there is a case where the postback always fails and I get a:

Validation of viewstate MAC failed. If this application is hosted by a Web Farm or cluster, ensure that configuration specifies the same validationKey and validation algorithm. AutoGenerate cannot be used in a cluster.

Here is the scenario to reproduce the error:

  1. Create a standard webform mypage.aspx with a button
  2. Create a Route that maps "a/b/{id}" to "~/mypage.aspx"
  3. When you execute the site, you can navigate http://localhost:XXXX/a/b/something the page works. But when you press the button you get the error. The error doen't happen when the Route is just "a/{id}".

It seems to be related to the number of sub-paths in the url. If there are at least 2 sub-paths the viewstate validation fails.

You get the error even with EnableViewStateMac="false".

Any ideas? Is it a bug?

Thanks

A: 

Are you using safari as a browser? if so then this will probably be a problem with a large float. Remove that float and things will work fine.

Mischa Kroon
if this is true, and about safari only, it would be good to have a reference link.
DrydenMaker
A: 

I had this same issue, I had some rogue

<form></form>

Tags, once I removed them from my page the error no longer came up.

JSmyth
+1  A: 

I also found this bug in asp.net mvc beta. It can be very reproduced. After create asp.net mvc application using the default template, add a asp:button control to page home.aspx in design view, hit f5, the home page is displayed properly. click the button, this error will show up. After some debugging into the mvc source code, I found it is caused by the ViewUserControl in site.master page, just comment the <% Html.RenderPartial("LoginUserControl"); %>, then the click event can be handled properly.

I also found that setting like enableViewStateMac="false" enableEventValidation="false" viewStateEncryptionMode="Never" is not useful.

In the mvc source code the following section handle the ViewUserControl rendering

public virtual void RenderView(ViewContext viewContext) {

// TODO: Remove this hack. Without it, the browser appears to always load cached output
viewContext.HttpContext.Response.Cache.SetExpires(DateTime.Now);
**ViewUserControlContainerPage containerPage = new ViewUserControlContainerPage(this);**
// Tracing requires Page IDs to be unique.
ID = Guid.NewGuid().ToString();
containerPage.RenderView(viewContext);

}

private sealed class ViewUserControlContainerPage : ViewPage {

public ViewUserControlContainerPage(ViewUserControl userControl) {
    Controls.Add(userControl);
}

}

the ViewUserControl always render in a newly created container page, this page will not pick your setting. In fact if step to this section, manually change the container.enableViewStateMac to false, does help to kill the error. So the only way to solve it is to ask Microsoft to change the mvc code.

A: 

This issue on Microsoft Connect:

http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=393619

Mauricio Scheffer
Closed as "by design"... Nice "design" Microsoft! :-/
Mauricio Scheffer
+7  A: 

I worked around this by having my view user control inherit from this class instead of ViewUserControl<T> (it's kind of a patch for RenderView). It did the trick for me, hopefully it works for you too.

public class ViewUserControlWithoutViewState<T> : ViewUserControl<T> where T : class {
    protected override void LoadViewState(object savedState) {}

    protected override object SaveControlState() {
        return null;
    }

    protected override void LoadControlState(object savedState) {}

    protected override object SaveViewState() {
        return null;
    }

    /// <summary>
    /// extracted from System.Web.Mvc.ViewUserControl
    /// </summary>
    /// <param name="viewContext"></param>
    public override void RenderView(ViewContext viewContext) {
        viewContext.HttpContext.Response.Cache.SetExpires(DateTime.Now);
        var containerPage = new ViewUserControlContainerPage(this);
        ID = Guid.NewGuid().ToString();
        RenderViewAndRestoreContentType(containerPage, viewContext);
    }

    /// <summary>
    /// extracted from System.Web.Mvc.ViewUserControl
    /// </summary>
    /// <param name="containerPage"></param>
    /// <param name="viewContext"></param>
    public static void RenderViewAndRestoreContentType(ViewPage containerPage, ViewContext viewContext) {
        string contentType = viewContext.HttpContext.Response.ContentType;
        containerPage.RenderView(viewContext);
        viewContext.HttpContext.Response.ContentType = contentType;
    }

    /// <summary>
    /// Extracted from System.Web.Mvc.ViewUserControl+ViewUserControlContainerPage
    /// </summary>
    private sealed class ViewUserControlContainerPage : ViewPage {
        // Methods
        public ViewUserControlContainerPage(ViewUserControl userControl) {
            Controls.Add(userControl);
            EnableViewState = false;
        }

        protected override object LoadPageStateFromPersistenceMedium() {
            return null;
        }

        protected override void SavePageStateToPersistenceMedium(object state) {}
    }
}

I blogged about this some time ago.

Mauricio Scheffer
+1 Awesome! Saved me from this: http://stackoverflow.com/questions/1278258/asp-net-mvc-webform-hybrid
orip
A: 

Just try to clear cookies on your local machine. Had same issue and this helped.

isuruceanu