Asp.Net MVC 5 связывает параметр исключительно с телом

Я хочу предотвратить публикацию конфиденциальных данных через строку запроса url в приложении MVC 5.

В MVC есть DefaultModelBinder. DefaultModelBinder ищет параметры ActionMethod в строке запроса url, в теле и маршруте. Но моя цель - привязать параметры исключительно от тела и не от строки маршрута или запроса.

В Asp.Net WebApi существует такая концепция. Атрибут [FromBody] выполнит задание: http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api

Есть ли что-то подходящее для MVC?

Я нашел System.Web.ModelBinding.FormAttribute (https://msdn.microsoft.com/en-us/library/system.web.modelbinding.formattribute(v=vs.110).aspx). Однако, если я украшу параметр, это не повлияет на привязку модели.

Ответ 1

По умолчанию связующее ищет данные в четырех местах: данные формы, данные маршрута, строку запроса и любые загруженные файлы.

Можно ограничить привязку к одному источнику данных. Для этого вы должны вызвать метод UpdateModel, как второй параметр, объект FormValueProvider (реализация IValueProvider).

public ActionResult Products()
{
    IList<Products> products = new List<Products>();
    UpdateModel(products, new FormValueProvider(ControllerContext));
    return View(products);
}

Полный список объектов (все они получают ControllerContext в качестве параметра contructor):

  • FormValueProvider: поиск данных в теле (Request.Form)
  • RouteDataValueProvider: поиск данных на маршруте (RouteData.Value)
  • QueryStringValueProvider: поиск данных в строке запроса (Request.QueryString)
  • HttpFileCollectionValueProvider: поиск загруженных файлов (Request.Files)

Ответ 2

Другой способ: создать привязку настраиваемой модели, которая использует FormValueProvider. Преимущество этого заключается в том, что вам не нужно изменять метод действия.

Пример:

[ModelBinder(typeof(PersonBinder))]
public class Person
{
    [DisplayName("Social Security Number")]
    public int SSN { get; set; }

    [HiddenInput(DisplayValue = false)]
    public string ShouldNotBind { get; set; }
}

public class PersonBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        bindingContext.ValueProvider = new FormValueProvider(controllerContext);
        Person model = (Person)bindingContext.Model ?? new Person();
        model.SSN = Convert.ToInt16(GetValue(bindingContext, "SSN"));
        return model;
    }

    private string GetValue(ModelBindingContext context, string name)
    {
        ValueProviderResult result = context.ValueProvider.GetValue(name);
        if (result == null || result.AttemptedValue == "")
        {
            return "<Not Specified>";
        }
        return result.AttemptedValue;
    }
}

И ваш метод действия:

[HttpPost]
public ActionResult Person(Person person)
{
    return View(person);
}

Даже если вы отправляете сообщение с запросом, свойство ShouldNotBind будет отображаться как "null".

Ответ 3

Почему бы не использовать форму? При отправке данных вашей почтовой формы