Сложный объект ModelBinder NHibernate с коллекциями - PullRequest
0 голосов
/ 06 сентября 2010

Ниже при начальной загрузке (Edit) все отображается нормально. Однако, когда я POST (Действие ниже), похоже, что он идет и пытается захватить модели ProductAttribute отдельно, с идентификатором продукта, который быстро завершается ошибкой. Как не допустить, чтобы моя реализация Binder пыталась повторно связать Коллекции как отдельные объекты?

Спасибо!

Модель

public class Product {
    virtual public long Id { get; set; }

    virtual public string Name { get; set; }

    private IList<ProductAttribute> _productAttributes;

    public virtual IList<ProductAttribute> ProductAttributes { 
        get{
        if(_productAttributes == null){
            _productAttributes = new List<ProductAttribute>();
        }
        return _productAttributes;
        }
        set{
        _productAttributes = value;
        }
    }
}

View

<%using (Html.BeginForm(new {id = Model.Id > 0 ? (long?)Model.Id : null})) {%>
<table class="form">
  <% for(var i=0; i < Model.ProductAttributes.Count; i++){ 
    var pa = Model.ProductAttributes[i]; %>
  <tr>
    <th><%: Model.ProductAttributes[i].Name %></th>
    <td>
    <%: Html.Hidden("ProductAttributes.Index", i) %>
    <% if(pa.CanSpecifyValueDirectly()){ %>
    <%: Html.TextBoxFor(model => model.ProductAttributes[i].Value) %>
    <% } else { %>
    <%: Html.DropDownListFor(model => model.ProductAttributes[i].Value, new SelectList(pa.MarketAttribute.AttributeLevels, "id", "Name", pa.AttributeLevel)) %>
    <% } %>
    </td>
  </tr>
  <input type="submit" value="Save" />
</table>
<%}%>

Контроллер

public ActionResult Edit(long id, Product product) {
    ViewData.Model = product;
    if (ModelState.IsValid) {
        var results = product.Update();
        ViewData["results"] = results;
        if (!results.Error) {
            return RedirectToAction("Show", new { id = id });
        }
    }

    return View();
}

Binder

public class StackModelBinder : DefaultModelBinder {
    protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType) {
        var modelInterface = modelType.GetInterface("IModel");
        if (modelInterface == null) {
            return base.CreateModel(controllerContext, bindingContext, modelType);
        }

        var value = bindingContext.ValueProvider.GetValue("id").RawValue.ToString();
        if (string.IsNullOrEmpty(value)) {
            return base.CreateModel(controllerContext, bindingContext, modelType);
        }

        var id = Convert.ChangeType(value, typeof (long));
        var assembly = Assembly.GetAssembly(modelType);
        var dao = assembly.GetType(string.Concat(assembly.GetName().Name, ".core.GlobalDao`1[", modelType.FullName, "]"));

        if (dao == null) {
            return base.CreateModel(controllerContext, bindingContext, modelType);
        }

        var method = dao.GetMethod("Get");
        return method.Invoke(null, new[] {id});
    }
}

1 Ответ

1 голос
/ 06 сентября 2010

Как правило, плохая идея проталкивать сущности через связыватель модели - они, как правило, слишком сложны для него, не говоря уже о захватывающих вещах, которые происходят в современных ORM, таких как динамические проксиможет дать ModelBinder или ORM подходит.

Ваша лучшая ставка здесь - изменить правила и создать специальный класс для внесения изменений и передачи их контроллеру.Этот класс может быть дружественным для ModelBinder, и вы получаете дополнительное преимущество отделения пользовательского интерфейса от сущностей домена.

...