MVC模型重复

时间:2012-06-24 00:36:01

标签: asp.net-mvc asp.net-mvc-3 model dry

我对ASP.NET MVC很新,所以如果这是我应该知道的,请原谅我。我还没有看到任何明显的文档,所以这里有:

我有一个LINQ to Entities数据模型和一个MVC项目。我使用了很多javascript / jquery,所以选择通过WebAPI从客户端访问我的数据作为json对象。但是,我不想将所有实体对象属性传递给客户端,因此我在我的MVC项目中添加了单独的模型,我在其中处理MVC模型验证和绑定到我的视图。另外,为了在我的jquery中使用它,我创建了模型的json版本。

这只是项目的开始,我不想错误地开始它。在我的业务层中为每个实体提供三个版本的模型将是一场噩梦!我确信我的项目的整体结构是非常常见的,但是看不到许多开发人员解决这种代码重复问题。必须有更好的方法来实施它。

有什么想法?真的很感激任何意见。

2 个答案:

答案 0 :(得分:1)

在回答上面的评论时 - 您可以将javascript viewmodel创建为标准的js对象。我倾向于使用Knockout.js,所以它看起来像这样:

jsController.Resource = function (data) {

    self.UserId = ko.observable(data.UserId);
    self.FullName = ko.observable(data.Name);
    self.RoleName = ko.observable(data.RoleName);
    self.RoleId = ko.observable(data.RoleId); 
} 

然后使用ajax post方法将其发布到您的MVC操作

jsController.addToUndertaking = function (resource, isAsync) {
    mylog.log("UndertakingId at post = " + jsController.undertakingId);

    var action = $.ajax({
        type: "POST",
        url: "/TeamMember/AddUserToUndertaking",
        data: resource,
        cache: false,
        async: isAsync
    });

    action.done(function () {
        resource.AllocatedToUndertaking(true);
    //Do other funky stuff
    });
};  

创建MVC操作,使其接受表单集合:

public ActionResult AddUserToUndertaking(FormCollection postedResource)
    {
        if (Request.IsAjaxRequest() == false)
        {
            const string msg = "Non ajax request received";
            Logger.ErrorFormat(msg);
            throw new SecurityException(msg);
        }

        if (postedResource == null)
        {
            Logger.Debug("Null resource posted - terminating.");
            return new HttpStatusCodeResult(500);
        }

        var resource = new AllocatedResourceAjaxViewModel(postedResource);
    //Do something Funky
       return new HttpStatusCodeResult(200);
    }

然后从窗体集合中创建MVC视图模型(我倾向于通过将窗体集合作为构造函数方法传递给viewmodel来实现此目的。)

public class AllocatedResourceAjaxViewModel
{
    public int UserId { get; set; }
    public string Name { get; set; }
    public string RoleName { get; set; }
    public int RoleId { get; set; }


    public AllocatedResourceAjaxViewModel()
    {}

    public AllocatedResourceAjaxViewModel(NameValueCollection formData)
    {
        UserId = JsFormDataConverter.Int(formData["UserId"]);
        Name = Convert.ToString(formData["FullName"]);
        RoleName = Convert.ToString(formData["RoleName"]);
        RoleId = JsFormDataConverter.Int(formData["RoleId"]);

    }

}

由于你的javascript VM中的null int会导致传递一串'undefined',你需要一个转换器方法来安全地提取非字符串。

public static class JsFormDataConverter
{
    public static bool Boolean(string formValue, bool defaultValue = false)
    {
        if (formValue.ToLower() == "true") return true;
        if (formValue.ToLower() == "false") return false;
        return defaultValue;
    }


    public static int Int(string formValue, int defaultValue = 0)
    {
        int result;
        return int.TryParse(formValue, out result) 
            ? result 
            : defaultValue;
    }

}

然后你去。我相信你可以改进上述内容,但这会让你前进。

答案 1 :(得分:0)

我一直以来的工作方式就是你有你的模型,例如订单& OrderLines,它存储您的所有数据,并通过SQL直接从数据库获得水分,或者(通常是现在)通过NHM或实体框架等ORM进行水合。

然后使用ViewModels - 这些用于将数据从应用程序传输到视图 - 直接,即绑定到OrderViewModel的强类型视图或通过返回JsonResult的操作。

OrderViewModel不是Order的重复,因为它只能保存需要在屏幕上显示的数据(如果您有许多不同的视图以不同的方式显示订单,那么有很多可以完全接受不同的ViewModels -one,每个视图只包含每个视图所需的字段)。 ViewModels也不应包含除其他ViewModel之外的任何复杂类型。这有助于防止意外的数据访问(考虑安全性和性能)。

所以给定

public class Order
{
    public int Id { get; set; }
    public DateTime OrderDate { get; set; }
    public User User { get; set; }
    public string  Description { get; set; }
    public List<OrderLine> OrderLines { get; set; }
}

public class OrderLine
{
    public int Id { get; set; }
    public Order Order { get; set; }
    public String Description { get; set; }
    public int Quantity { get; set; }
    public int Weight { get; set; }
    public int Price { get; set; }
}

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
}

您可以拥有两个ViewModel

public class OrderViewModel
{
    public int ID { get; set; }
    public List<OrderLineViewModel> OrderLines { get; set; }
    public DateTime OrderDate { get; set; }
    public int UserId { get; set; }
    public string Description { get; set; }
}

public class OrderLineViewModel
{
    public int Id { get; set; }
    public int OrderId { get; set; }
    public String Description { get; set; }
    public int Quantity { get; set; }
    public int Weight { get; set; }
    public int Price { get; set; }
}

然后可以根据需要将视图模型序列化为JSON,或使用验证属性等标记。