I can't make ValidateInput(False) work - A pot

2019-06-27 04:24发布

问题:

I have tried so many combinations, but cannot get the validation to turn off on this code block

[ValidateInput(false)]
    public ActionResult aSavePageCopy()
    {
        aLoggedIn();
        int id = Convert.ToInt32(Request.Form["id"]);
        PagesDataContext pdc = new PagesDataContext();
        Page p = pdc.Pages.Single(row => row.ID == id);

        p.PageCopy = Request.Form["PageCopy"];

        pdc.SubmitChanges();

        return Redirect("/Admin/aViewPages");
    }

It seems that this works for others so I don't see what I'm missing here. The error I get is A potentially dangerous Request.Form value was detected from the client

回答1:

You could use FormCollection which is safe to access instead of Request.Form (but please don't use it, see below for the real solution to your problem):

[ValidateInput(false)]
public ActionResult aSavePageCopy(FormCollection fc)
{
    aLoggedIn();
    int id = Convert.ToInt32(fc["id"]);
    PagesDataContext pdc = new PagesDataContext();
    Page p = pdc.Pages.Single(row => row.ID == id);

    p.PageCopy = fc["PageCopy"];

    pdc.SubmitChanges();

    return Redirect("/Admin/aViewPages");
}

Of course that's an absolutely ridiculous and lousy way to solve the problem. The correct way to do it is to use a view model (of course):

public class MyViewModel
{
    public int Id { get; set; }
    public string PageCopy { get; set; }
}

and then:

[ValidateInput(false)]
public ActionResult aSavePageCopy(MyViewModel model)
{
    aLoggedIn();
    PagesDataContext pdc = new PagesDataContext();
    Page p = pdc.Pages.Single(row => row.ID == model.Id);

    p.PageCopy = model.PageCopy;

    pdc.SubmitChanges();

    return Redirect("/Admin/aViewPages");
}

or if you are using ASP.NET MVC 3 and wanted to disable validation only for a single property on your view model instead of doing it for the entire request you could decorate this view model property with the [AllowHtml] attribute:

public class MyViewModel
{
    public int Id { get; set; }
    [AllowHtml]
    public string PageCopy { get; set; }
}

and then you no longer need the [ValidateInput(false)] attribute on your action:

public ActionResult aSavePageCopy(MyViewModel model)
{
    aLoggedIn();
    PagesDataContext pdc = new PagesDataContext();
    Page p = pdc.Pages.Single(row => row.ID == model.Id);

    p.PageCopy = model.PageCopy;

    pdc.SubmitChanges();

    return Redirect("/Admin/aViewPages");
}

Not only that we have solved the problem but as you can see you no longer need to write any plumbing code in your controller action parsing around integers and stuff which is the role of the model binder.