AllowHtml not working for ASP.Net Mvc 3 site

2020-03-21 10:24发布

问题:

We're trying to use the [AllowHtml] decoration on one of our ViewModel properties so that we can avoid the YSOD:

A potentially dangerous Request.Form value was detected from the client (RequestText="<br>").

when we try to submit html text, like: <br>. We want to then use Server.HtmlEncode within the controller action to prevent attacks, but when we decorate the property with [AllowHtml] it has no affect, and if we try to use [ValidateInput(false)] on the controller action, it has no effect either. We saw a StackOverflow Post saying that in MVC 3 RC2 that you have to add:

ModelMetadataProviders.Current = new DataAnnotationsModelMetadataProvider(); to the global.asax

We tried that too, even though we are using the release version of MVC 3, not RC2, but that had no effect either. Does anyone know how to fix this?

Model:

namespace UI.Models.ViewModel
{
    public class CustomerRequestSupport
    {
        /// <summary>
        /// Gets or Sets the textual description entered by the Customer for 
        /// the support requested.
        /// </summary>
        [AllowHtml]
        public string RequestText { get; set; }
    }
}

Controller:

    [HttpPost]
    [TabsActionFilter]
    public ActionResult RequestSupport(CustomerRequestSupport collection)
    {
        if (ModelState.IsValid)
        {

            Ticket ticket = new Ticket();

            ticket.Requestor = LoggedInCustomer;

            ticket.Summary = "General Support Ticket";
            ticket.Notes = Server.HtmlEncode(collection.RequestText);

            var errors = _ticketService.SubmitTicket(ticket);

            if (errors.Any())
            {
                ModelState.AddModelError("collection",
                    String.Format("An error has occurred in your Request for Support: " +
                    "{0} Please try again later or call the help desk " +
                    "for immediate assistance.",
                    errors.Aggregate((acc, st) => acc + " " + st)));
            }
            else
            {
                TempData["FlashMessage"] = String.Format("Your request for support has been " +
                        "submitted, the Ticket Number is: {0}.", ticket.TicketNumber);

                return AutoMapView<CustomerDetails>(View("Details", base.LoggedInCustomer));
            }
        }

        //needed for tabs to show
        ViewData.CustomerContactSet(base.LoggedInCustomer);

        return View();

View:

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

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
 Request Support
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="PageTitle" runat="server">
 Request Support
</asp:Content>

<asp:Content ID="Content3" ContentPlaceHolderID="MainContent" runat="server">
<% using (Html.BeginForm())
   { %>
    <%= Html.ValidationSummary() %>
    <h2>Enter a description of the support needed</h2>
    <%: Html.TextAreaFor( m => m.RequestText, 4, 90, null) %>
    <input type="submit" value="Submit" />
<% } %>
</asp:Content>
<asp:Content ID="Content4" ContentPlaceHolderID="JavaScriptContent" runat="server">
</asp:Content>

回答1:

In his answer Darin is definitely onto something when he asks

So you gotta be doing something different than what I showed here. What is it?

I am guessing you have something else affecting the ASP.NET pipeline that is accessing the FormCollection prior to your [AllowHtml] being taken into account. Off the top of my head some common ASP.NET MVC OSS libraries that touch the pipeline are ELMAH, Glimpse, WebActivator, MvcContrib, there are many more but you get the idea.

I have to believe you are using one of the tools above or something similar. Assuming you are make sure you are on the latest release of each and check their open bug reports.

Finally, a quick way to determine if its your code, your MVC instance or an OSS library would be to create a test project. Try creating a vanilla ASP.NET MVC project. Ensure that AllowHtml works. Then add in your various OSS components until it breaks. Just be sure when you are adding in OSS components that the versions match what you are using in your current project.



回答2:

You gotta be doing something wrong. Unfortunately as you haven't shown your example we cannot know what you are doing wrong. So let me write you a full working example:

Model:

public class MyViewModel
{
    [AllowHtml]
    public string RequestText { get; set; }
}

Controller:

public class HomeController: Controller
{
    public ActionResult Index()
    {
        var model = new MyViewModel
        {
            RequestText = "<strong>Hello World</strong>";
        };
        return View(model);
    }

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

View:

@model MyViewModel
@using (Html.BeginForm())
{
    @Html.TextAreaFor(x => x.RequestText)
    <button type="submit">OK</button>
}

So you gotta be doing something different than what I showed here. What is it?