接口实现接口作为ASP.NET MVC 4中的View模型

时间:2013-07-15 22:10:23

标签: asp.net asp.net-mvc

我有一个接口IBasicData,用于为用户信息(继承代码)实现IVeryBasicData

public interface IBasicData:IVeryBasicData
{
    byte[] Password { get; set; }
    string Email { get; set; }
}

public interface IVeryBasicData:IUser
{
    string Name { get; set; }
    string UserId { get; set; }
    string Description { get; set; }
    string Url { get; set; }
}
public interface IUser
{
    DateTime CreationTime { get; set; }
    string PartitionKey { get; set; }
    string RowKey { get; set; }
}

然后我有一个来自UsersDataSource的方法GetUsers返回IQueryable<IBasicData>,我希望能够将这个IQueryable用作View的模型。但是当我尝试这样做时会出现异常:例如,在@Hml.DisplayNameFor(model => model.UserId)中调用它们时无法找到属性。

所以,我已经找到了这个解决方案:

foreach (var user in usersDataSource.GetUsers())
        {
            var addUser = new UserViewModel()
            {
                CreationTime = user.CreationTime,
                Description = user.Description,
                Email = user.Email,
                Name = user.Name,
                PartitionKey = user.PartitionKey,
                Password = user.Password,
                RowKey = user.RowKey,
                Url = user.Url,
                UserId = user.UserId
            };
            usersViewModel.Add(addUser);
        }
        return View(usersViewModel);

UserViewModel是一个实现IBasicData的类。这可行,但对我来说似乎相当丑陋是否有更好的方法可以将IQuaryable<IBasicData>用作View模型?

2 个答案:

答案 0 :(得分:1)

更新您的视图,首先在模型声明中获取IEnumerable。

查看

@model IEnumerable<IBasicData>

@{foreach(var user in Model){
     //I don't know how you are wanting to render out the data...example only
     @user.Email<br/>
     @user.Name
}}

然后,在您的控制器中,您应该能够执行以下操作:

var modelData = usersDataSource.GetUsers().Select(user=>new UserViewModel{
                CreationTime = user.CreationTime,
                Description = user.Description,
                Email = user.Email,
                Name = user.Name,
                PartitionKey = user.PartitionKey,
                Password = user.Password,
                RowKey = user.RowKey,
                Url = user.Url,
                UserId = user.UserId
            }).ToList();
return View(modelData );

调用.ToList()会使查询立即执行并在转到View之前检索数据。

答案 1 :(得分:0)

您确定不会抛出异常,因为在IBasicData接口的对象上运行的模型绑定器只知道密码和电子邮件属性 - 模型绑定器可能使用反射并且可能没有获取基本接口吗?

引自This article on MSDN Magazine,强调我的

  

例如,即使Microsoft .NET Framework提供   对面向对象原则的出色支持   DefaultModelBinder提供不支持绑定到抽象基础   类和接口。

老实说,我建议您让ViewModel类显式实现所有3个接口,然后将实际EF实体的投影保持在此类的实例中(即usersDataSource.Select(u =&gt; new UserViewModel { ...});然后使用@model IEnumerable

绑定视图

接口继承听起来不像这里的正确方法;我不担心你的投影代码,这很正常,请记住它在你的EF层和你的表层(View)之间提供了一个很好的分离。

我同意Tommy虽然在IEnumerable上;一旦你离开你的EF层,IEnumerable就是你的数据,以便实现数据并尽快关闭数据库连接。