0

У меня есть метод действия без параметров.Впоследствии привязка модели в ASP.NET MVC: как преобразовать значения QueryString в модель представления?

В коллекции QueryString содержатся все мои значения. Клавиши QueryString соответствуют моим свойствам модели просмотра.

var queryStringValueProvider = new QueryStringValueProvider(ControllerContext); 
var providerResult = queryStringValueProvider.GetValue(ValidationKeys.Id); // ?! 

var viewModelTypeName = queryString[ValidationKeys.ViewModelType]; 

var viewModelType = Type.GetType(viewModelTypeName); 
var viewModelInstance = providerResult.ConvertTo(viewModelType); // throws an InvalidOperationException 

Как я могу преобразовать QueryString коллекции в модель представления? ASP.NET MVC уже делает это, когда вы просто передаете модель представления в параметры метода действия. Так что мне нужно, это после привязки модели с использованием механики ASP.NET MVC.

+0

Это может ответить на ваш вопрос. http://stackoverflow.com/questions/627838/asp-net-mvc-getting-querystring-values ​​ – Ademar

+0

@Ademar Нет, это не так. Имена параметров/имена свойств известны только во время выполнения. Я пытаюсь проверить входные данные пользователя с помощью атрибута RemoteAttribute. Я хочу иметь один метод действий, который обрабатывает удаленные проверки для свойств, которые должны быть уникальными. – Rookian

ответ

0

My Controller Действие

var viewModelTypeName = queryString[ValidationKeys.ViewModelType]; 
var viewModelType = Type.GetType(viewModelTypeName); 
var instance = Activator.CreateInstance(viewModelType); 
UpdateModelUsingQueryString(instance); 

UpdateModel

protected internal void UpdateModelUsingQueryString<TModel>(TModel model) where TModel : class 
{ 
    if (model == null) throw new ArgumentNullException("model"); 

    Predicate<string> propertyFilter = propertyName => new BindAttribute().IsPropertyAllowed(propertyName); 
    var binder = Binders.GetBinder(typeof(TModel)); 

    var bindingContext = new ModelBindingContext() 
    { 
     ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, model.GetType()), 
     ModelState = ModelState, 
     PropertyFilter = propertyFilter, 
     ValueProvider = new QueryStringValueProvider(ControllerContext) 
    }; 
    binder.BindModel(ControllerContext, bindingContext); 
} 

Проблема заключалась в том, что UpdateModel или TryUpdateModel не работает для object по дизайну. Оба метода используют typeof(TModel). Но вы должны использовать model.GetType().

Взгляните: Model Binding - Type in External Assembly

Дарин Димитров дал правильный ответ :)

0

Для ручной привязки модели создайте собственное связующее устройство (реализуйте IModelBinder) и зарегистрируйте его в контейнере IoC.

Или вы можете позвонить по телефону this.UpdateModel в свой метод действия. Это должно привязать значения из вашего ValueProvider (RouteData, Request.Form collection и QueryString) к вашей модели.

+0

Как IoC относится к моему вопросу: o? – Rookian

+0

MVC будет использовать ваш контейнер IoC для разрешения привязки модели. Если вы создадите собственное связующее устройство, вам необходимо зарегистрировать его в контейнере IoC. –

+0

Почему мне нужно написать собственное связующее устройство? – Rookian

0

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

Это также может быть встроено в метод расширения, поэтому его можно было бы назвать «по требованию», а не при строительстве.

0

Вы можете использовать TryUpdateModel

public ContentResult TestAction() 
{ 
    var model = new MyModel(); 

    if(TryUpdateModel(model, new QueryStringValueProvider(ControllerContext))) 
    { 
     return Content("success"); 
    } 

    return Content("failed"); 
} 
+0

Вы попробовали сами? – Rookian

+0

@Rookian. Вы задали вопрос, на который я ответил. Это до вас, чтобы попробовать или нет. – VJAI

+0

Ну, если вы знаете, модель TryUpdateModel отлично работает. Но я не знаю модель, но ее тип. – Rookian