Как сохранить механизм связывания ASP.NET от ненужного вызова свойств только для чтения при создании объекта класса? - PullRequest
0 голосов
/ 04 мая 2018

У нас есть веб-приложение, использующее ASP.NET MVC, которое поддерживает методы контроллера, которые принимают объект класса в качестве параметра. Существует автоматическое связывание опубликованных значений формы для создания и заполнения объекта класса, что происходит еще до того, как будет вызван фактический код метода контроллера. Пока все хорошо, но вот моя проблема: в процессе конструирования объекта класса механизм связывания ASP.NET вызывает каждое открытое свойство класса. Некоторые из этих свойств включают в себя некоторые дорогостоящие вычисления (итерация внутренних списков, подсчет операций и т. Д.), И раздражает, что их вызывают без всякой причины и отбрасывают значения. Это свойства, доступные только для чтения, с только «get» и без «set», поэтому связыватель не может касаться их для назначения им значений. Как мы можем предотвратить это?

Вот то, что до сих пор безуспешно пробовалось:

  1. Используйте [Bind (Include = "...")] в объявлении метода контроллера, чтобы ограничить другие (не только для чтения) свойства, которые фактически могут быть назначены.
  2. Используйте аннотацию [BindNever] для свойств только для чтения в определении класса.

Наш текущий обходной путь заключается в том, что мы просто полностью отказываемся от реализации свойства только для чтения и переписываем их все как методы. Связующий код не вызывает методы, поэтому это работает, но мы все равно предпочли бы иметь их в качестве свойств, и это похоже на проблему, которая должна быть способной к решению. Есть какие-нибудь мысли?

== РЕДАКТИРОВАТЬ =============

В ответ на приведенные здесь ответы попробовал дополнительные вещи, которые все еще не работали:

  1. Используйте [Bind (Exclude = "...")] в объявлении метода контроллера, указав свойства, которые мы не хотим вызывать. (Они все равно вызываются.)

== РЕДАКТИРОВАТЬ 2 =============

Дополнительные детали по запросу. Я использую VS 2015, .NET Framework 4.5.2. Только сейчас я создал пример программы для демонстрации проблемы:

  1. Файл -> Создать -> Проект -> Веб -> Веб-приложение ASP.NET
  2. В разделе «Шаблоны ASP.NET 4.5.2» выберите «MVC»
  3. В ManageViewModels.cs есть класс с именем «AddPhoneNumberViewModel». Этот класс встречается как параметр метода ManageController.AddPhoneNumber (версия HttpPost). Добавьте открытое свойство в класс с именем «PropertyThatShouldNeverBeCalled» и поместите в него точку останова (см. Пример кода ниже).
  4. Скомпилируйте и запустите приложение в режиме отладки. Чтобы получить доступ к конечной точке / Manage / AddPhoneNumber, вам нужно будет создать учетную запись, затем снова получить доступ к конечной точке, ввести номер телефона и нажать «Отправить».
  5. Обратите внимание, что вы достигли своей точки останова в PropertyThatShouldNeverBeCalled.
  6. Попробуйте одно из неудачных исправлений, описанных выше (например, добавьте [Bind (Exclude = "PropertyThatShouldNeverBeCalled")] к определению ManageController.AddPhoneNumber).
  7. Повторите шаг 4 выше. Заметьте, что вы все еще достигли своей точки останова.

Пример кода 1 (из ManageViewModel.cs):

public class AddPhoneNumberViewModel
{
    [Required]
    [Phone]
    [Display(Name = "Phone Number")]
    public string Number { get; set; }

    public bool PropertyThatShouldNeverBeCalled
    {
        get
        {
            bool returnVal = true;  // place breakpoint here
            return returnVal;
        }
    }
}

Пример кода 2 (из ManageController.cs):

    //
    // POST: /Manage/AddPhoneNumber
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> AddPhoneNumber([Bind(Exclude = "PropertyThatShouldNeverBeCalled")]AddPhoneNumberViewModel model)
    {
         // etc.
    }

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

Ответы [ 2 ]

0 голосов
/ 04 мая 2018

Вы можете использовать атрибут [Bind(Exclude="...")] для типа объекта в качестве параметра для контроллера:

Пример:

[HttpPost]
public ActionResult Post([Bind(Exclude = "PropertyName")] MyClass dataIn)
{
... 
}

MyClass являющийся объектом, который привязывается к данным, поступающим в действие контроллера. Exclude= принимает строку с разделителями-запятыми для всех свойств, которые вы не хотите включать в привязку модели. https://msdn.microsoft.com/en-us/library/system.web.mvc.bindattribute.exclude(v=vs.118).aspx

0 голосов
/ 04 мая 2018

Вы должны использовать модель POCO, такую ​​как DTO (объект переноса домена) или модель представления, которая содержит только свойства, которые необходимо связать (с любой проверкой, которую вы также хотите иметь для обработки ASP.NET), а затем передать эту информацию. модель в остальной части вашего приложения для потребления по мере необходимости.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...