Problem with MVC3 AllowHtml attribute

2019-06-15 11:29发布

问题:

I have a web app based on MVC3 (no beta or release candidate, RTM/RTW version) that has an action that accepts XML files for processing.

Of course, this seems evil to MVC because of possible attacks, so it doesn't allow it. Well, I try to put either AllowHtml on the model object as such:

   public class XMLModel
    {
        [AllowHtml]
        public string msg { get; set; }
    }

Or I set ValidateInput to false on my action method such as this:

    [ValidateInput(false)]
    public ActionResult AddCDR(XMLModel model)
    {
    }

The reason for having a "strongly" typed model in the first place was that I originally tried to have a string value named "msg" as the action method parameter, but that always came back empty.

Now, when someone posts to this form, either on the same machine or from a networked computer, the msg field is always blank.

I have verified with WireShark that the data is actually in the request.

Now, one interesting thing. This should not be necessary with MVC 3. Yet it makes a slight difference.

If I add this to my web config:

<httpRuntime requestValidationMode="2.0" />

It works for requests originating from the local computer, but it does NOT work from another system.

I think the AllowHtml version seems elegant - if only it worked.

I have also found out about a bug in RC2 - again, this should not affect me, but I tried to add the following in Application_Start() anyway:

ModelMetadataProviders.Current = new DataAnnotationsModelMetadataProvider();

As expected, it makes no real difference.

Everything works as expected on my development computer (Win7x64, VS2010), but on the target system (Win2008R2x64, IIS7.5) the above problems are giving me a hard time.

Very important point to note: If I post to the action with no angle brackets, I get the form data as expected. As soon as the angle brackets show up, though, either my action isn't called at all, or it doesn't find the form data, neither in action method parameters or in for instance Request.Params["msg"] where it should be.

Any ideas to allow the XML through?

UPDATE

I've tried to work my way around this while waiting for anyone to come up with an answer here. I have not been able to solve it yet, but I have checked a few additional details;

  • First, I verified that the ASP.NET MVC 3 version installed on both my development computer and on the web server is the same; v3.0.20105.0 (according to Add/Remove programs).
  • The web application was actually created with the MVC3 beta, then converted to RC1 and RC2 as they came out, and finally to the RTM version. This meant I had to modify some code because of the ViewBag change. However, since I didn't know exactly what else had changed, I created a brand new MVC3 application with the RTM version, created a controller by the same name, with the same action method, taking a model object similar to the currently used one, renamed the old web app directory and put this new one in place. Exactly the same thing happens - i.e. the parameter with the AllowHtml attribute comes through with all content when the request is made from the local machine, but if it comes from a remote machine, then the HTML (XML actually) is stripped out.
    • There is no exception. I've installed Elmah and verified this - no exception occurs, my action method is apparently just called with anything looking like XML stripped out from the parameters to the method.

Needless to say, this is driving me crazy. I had some advice yesterday to look at the source code of MVC3, but unfortunately that doesn't really help me, as I can't see anything obviously wrong there, and I can't debug code on the server in question.

Any insights still highly desired, thanks! :)

回答1:

I cannot reproduce this.

Model:

using System.Web.Mvc;

namespace MvcApplication3.Models {
    public class XmlModel {
        [AllowHtml]
        public string msg { get; set; }
    }
}

Controller:

using System.Web.Mvc;
using MvcApplication3.Models;

namespace MvcApplication3.Controllers {
    public class HomeController : Controller {
        public ActionResult Index() {
            return View();
        }

        [HttpPost]
        public ActionResult Index(XmlModel model) {
            return View();
        }
    }
}

View:

@model MvcApplication3.Models.XmlModel

@using (Html.BeginForm()) {
    <div class="editor-label">
        @Html.LabelFor(model => model.msg)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.msg)
        @Html.ValidationMessageFor(model => model.msg)
    </div>
}

These were added to a default empty MVC 3 project. Everything posts fine. When I remove [AllowHtml], it generates the appropriate error message.



回答2:

I am answering this myself because this was an obscure situation, and MVC3 was not the problem.

The system that POSTed data to my application was doing so with malformed data. In addition to that, I was told that they were also POSTing to an older MVC2 application that worked just fine - this was wrong, it turned out they were GETting in that case, and GET they happen to do correctly.

If anything, fairly thorough testing has confirmed that the AllowHtml attribute actually works very well. Never trust your input, tho. :)