Создание объект средствами MVC Default Model Binding
От: curt_russel  
Дата: 06.06.13 18:58
Оценка:
Всем привет!

MVC Default Model Binding сам разбирает входные значения полей и подсовывает под указанную модель, т.е.

есть модель:
class Person {
  public string Name {get;set;}
  public string Age {get;set;}
}


действие:
[HttpPost]
public ActionResult SaveData(Person model) {
 ...
}


и вьюха с
@Html.BeginForm("SaveData", "Home", FormMethod.Post) {
  @Html.EditorFor(model.Name, ...)
  @Html.EditorFor(model.Age,...)
  <input type="submit" text="Save"/>
}


при сабмите значения из Request.Form транслируются в объект типа Person.

У меня другая ситуация — у меня нет ни Request.Form, ни Request.QueryString
Допустим, имя класса (полное), например, "Front.Models.Person" и словарь Поле/Значение, например, ["Name"]/["Serg"]; ["Age"]/[28] я получил из базы.
Нужно точно так же, средствами MVC Default Model Binding (DMB), получить на выходе объект этого класса.
Именно НЕ руками через рефлекшн, а средствами DMB!

Можно ли осуществить задуманное?
Re: Создание объект средствами MVC Default Model Binding
От: Doc Россия http://andrey.moveax.ru
Дата: 07.06.13 00:57
Оценка:
Здравствуйте, curt_russel, Вы писали:

_>У меня другая ситуация — у меня нет ни Request.Form, ни Request.QueryString

_>Допустим, имя класса (полное), например, "Front.Models.Person" и словарь Поле/Значение, например, ["Name"]/["Serg"]; ["Age"]/[28] я получил из базы.
_>Нужно точно так же, средствами MVC Default Model Binding (DMB), получить на выходе объект этого класса.
_>Именно НЕ руками через рефлекшн, а средствами DMB!

А почему бы не использовать ControllerFactory для этого?

Ну а серьезно — у Model Binder вполне конкретная цель, а у DMB еще и конкретная реализация. Чисто теоретически, можно попробовать сэмулировать Web запрос из словаря создать QueryString и правда без рефлекшена не получится по имени класса (строке) получить его экземпляр. Но IMHO лучше уж тогда написать свой биндер.
Re: Создание объект средствами MVC Default Model Binding
От: pavel783  
Дата: 07.06.13 09:02
Оценка:
_>У меня другая ситуация — у меня нет ни Request.Form, ни Request.QueryString
_>Допустим, имя класса (полное), например, "Front.Models.Person" и словарь Поле/Значение, например, ["Name"]/["Serg"]; ["Age"]/[28] я получил из базы.
_>Нужно точно так же, средствами MVC Default Model Binding (DMB), получить на выходе объект этого класса.
_>Именно НЕ руками через рефлекшн, а средствами DMB!

_>Можно ли осуществить задуманное?


DMB на входе прнимает HttpContext, который вне aspnet/webservice не сущ-т, так что можно просто сделать request в котором словарь упакуется в querystring url'а и тогда Action метод уже будет иметь HttpContext и Querytring. или еще в утилите Reflector есть плагин filedisasembler — можно исходники dmb выдрать и заменить в них httpcontext и иже с ним входные данные на более абстрактные данные, dmb тогда будет более универсальным...
Re[2]: Создание объект средствами MVC Default Model Binding
От: Doc Россия http://andrey.moveax.ru
Дата: 07.06.13 11:25
Оценка:
Здравствуйте, pavel783, Вы писали:

P> или еще в утилите Reflector есть плагин filedisasembler — можно исходники dmb выдрать и заменить в них httpcontext и иже с ним входные данные на более абстрактные данные, dmb тогда будет более универсальным...


А можно не заниматься ерундой и сделать декоратор. Ну а если сильно хочется сорцы, то опять же не возиться с Reflector. ASP.NET уже давно OpenSource. Вот этот биндер (и прочие сорцы там же на http://aspnetwebstack.codeplex.com)

http://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/DefaultModelBinder.cs
Re[3]: Создание объект средствами MVC Default Model Binding
От: curt_russel  
Дата: 14.06.13 13:45
Оценка:
Здравствуйте, Doc, Вы писали:

Doc>Здравствуйте, pavel783, Вы писали:


P>> или еще в утилите Reflector есть плагин filedisasembler — можно исходники dmb выдрать и заменить в них httpcontext и иже с ним входные данные на более абстрактные данные, dmb тогда будет более универсальным...


Doc>А можно не заниматься ерундой и сделать декоратор. Ну а если сильно хочется сорцы, то опять же не возиться с Reflector. ASP.NET уже давно OpenSource. Вот этот биндер (и прочие сорцы там же на http://aspnetwebstack.codeplex.com)


Doc>http://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/DefaultModelBinder.cs



Спасибо большое за советы!
Кому интересно, решение этой задачи:


private void Run()
{
    var dictionary = {параметры из БД}.ToDictionary(vmv => vmv.ParameterName,vmv => vmv => vmv.ParameterValue);

    var dictionaryValueProvider = new DictionaryValueProvider<object>(dictionary, CultureInfo.CurrentCulture);
    GenerateModel(ctrl.ModelName, dictionaryValueProvider);
}

private object GenerateModel(string modelName, DictionaryValueProvider<object> dictionaryValueProvider)
{
    var type = Type.GetType(modelName, false, true);
    var model = Activator.CreateInstance(type);

    CmsTryUpdateModel(model, dictionaryValueProvider);
    return model;
}

protected internal bool CmsTryUpdateModel<TModel>( TModel model, IValueProvider valueProvider ) where TModel : class
{
    if (model == null)
    {
        throw new ArgumentNullException("model");
    }
    if (valueProvider == null)
    {
        throw new ArgumentNullException("valueProvider");
    }

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

    var bindingContext = new ModelBindingContext() {
        // in the original method you have:
        // ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, typeof(TModel)),
        ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, model.GetType()),  // нужно GetType, т.к. тип известен только в runtime
        ModelName = null,
        ModelState = ModelState,
        PropertyFilter = propertyFilter,
        ValueProvider = valueProvider
    };
    binder.BindModel(ControllerContext, bindingContext);
    return ModelState.IsValid;
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.