【问题标题】:autofac not binding data in viewmodelautofac没有在viewmodel中绑定数据
【发布时间】:2014-08-02 04:33:24
【问题描述】:

我有一个接口,它的属性是另一个接口的列表和一个实现该接口的类,我为 Autofac 注册了它,但我的问题是 Autofac 没有将数据绑定到我的类,我在下面编写了代码:

我的界面:

public interface IDetail
{
    int Id { get; set; }

    string Name { get; set; }
}

public interface IMaster
{
    int Id { get; set; }

    DateTime Description { get; set; }

    List<IDetail> Details { get; set; }
}

我的课程:

public class Detail : IDetail
{
    public int Id { get; set; }

    public string Name { get; set; }
}

public class Master : IMaster
{
    public int Id { get; set; }

    public DateTime Description { get; set; }

    public List<IDetail> Details { get; set; }
}

我的控制器:

public class HomeController : Controller
    {
        IMaster _t;

        [HttpPost]
        public ActionResult Create(IMaster t)
        {
            _t = t;
        }


    }

我的 Autofac 注册:

    public class DependencyConfigure
        {
//Initializing
            public static void Initialize()
            {
                RegisterServices();
            }

//Registering
            private static void RegisterServices()
            {

                ContainerBuilder builder = new ContainerBuilder();

                builder.RegisterAssemblyTypes(
                    typeof(MvcApplication).Assembly
                    ).PropertiesAutowired();            

                builder.RegisterType<ExtensibleActionInvoker>()
                .As<IActionInvoker>()
                .WithParameter("injectActionMethodParameters", true);
                        builder.RegisterControllers(Assembly.GetExecutingAssembly())
                            .InjectActionInvoker();

                builder.RegisterType(typeof(Master)).As(typeof(IMaster));

                var container = builder.Build();
                DependencyResolver.SetResolver(new AutofacDependencyResolver(container));            
            }

        }

视图就在这里:

@model WebApplication1.Models.Master

@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()

        <div class="form-group">
            @Html.LabelFor(model => model.Description, new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.Description)
                @Html.ValidationMessageFor(model => model.Description)
            </div>
        </div>

        <div>
            @Html.Label("Details.Name", new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.Editor("Details[0].Name")                
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

换句话说,当我提交时,数据没有绑定到 Master.Details...

【问题讨论】:

  • 你的接口没用。接口旨在隐藏行为,但您隐藏的是数据。您的视图模型对象是带有数据的普通 DTO;没有行为。这些不应该由您的 DI 库构建。 DI 库旨在构建服务的对象图。请阅读newables and injectables之间的区别。
  • @Html.Editor("Details.Name") 实际呈现的是什么?可能应该是 @Html.EditorFor(m =&gt; m.Details) 才能正确显示 Details.IDDetails.Name 的索引属性

标签: c# asp.net-mvc interface inversion-of-control autofac


【解决方案1】:

你在这里做错了一些事情。

  1. Autofac 与模型绑定无关。 Autofac 用于将依赖项注入到控制器的构造函数中; ASP.NET MVC 模型绑定器将 HTTP 请求绑定到操作参数。它们是完全独立的关注点。 摆脱您的 IMaster 依赖注入。
  2. MVC 无法将表单发布绑定到接口,因为它不知道要实例化什么具体类型。忘记IMaster 接口并使用具体的视图模型类型。
  3. 表单帖子绑定到 action 参数,而不是 constructor 参数。您应该有一个接受 Master 对象的操作方法。

假设这是您的索引操作,您的HomeController 中应该有一个类似这样的操作方法:

[HttpPost]
public ActionResult Index(Master model)
{
    ...
}

您可能需要进行其他更改才能到达目的地,但这应该会让您走上正确的轨道(现在您的代码看起来很混乱)。

【讨论】:

  • 当您使用单独的模块时,通常在控制器中使用接口,因为您的具体类不在控制器的模块中,所以您不仅必须使用接口而不是类,而且autofac 是出于这样的原因创建的......
  • 不,不是。您在依赖注入和模型绑定之间感到困惑。如果你想将你的视图模型绑定到你的action,你需要一个具体的类,而autofac不会帮助你。您从根本上误解了 ASP.NET MVC 模型绑定的作用。
【解决方案2】:

正确答案在这里,出于这些原因,您需要在将数据绑定到视图模型之前将自定义绑定器写入 mvc,创建视图模型实例,然后将数据绑定到视图模型。您可以在此处查看活页夹示例(由我亲爱的高级开发人员 @Saeed Hamed 编写)

public class InterfaceModelBinderProvider : IModelBinderProvider
{
    public IModelBinder GetBinder(Type modelType)
    {
        if (modelType.IsInterface)
        {
            return new InterfaceModelBinder();
        }
        return null;
    }
}
public class InterfaceModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var item = DependencyResolver.Current.GetService(bindingContext.ModelType);

        bindingContext.ModelMetadata = new ModelMetadata(new DataAnnotationsModelMetadataProvider(),
            bindingContext.ModelMetadata.ContainerType, () => item, item.GetType(), bindingContext.ModelName);

        return base.BindModel(controllerContext, bindingContext);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-07
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    • 2014-05-12
    • 1970-01-01
    相关资源
    最近更新 更多