MVC 5 ViewModel中的计算属性而不是Model Class

时间:2014-12-20 00:33:03

标签: c# asp.net-mvc razor model asp.net-mvc-viewmodel

  

我搜索了StackOverflow和MSDN,发现了几个页面   感觉会帮助我,但一旦我尝试在那里实施解决方案   总是与我需要的东西略有不同,所以现在我   经过几个小时的拔毛。

问题:我的模型类中有计算属性。类名称为“渲染”,表示“照片渲染”的模型。计算的属性将用作Zip文件的名称,我将在ONE VIEW上为用户打包,具体取决于它们所在的“渲染详细信息”页面。显然,我们不希望在模型中执行此操作,因为并非每个视图或大多数视图都将使用它。

问题:如何将此计算属性移动到我的ViewModel中?

下面你会看到我现在的工作......

  • 渲染班级
  • 查看模型
  • Controller&
  • 适用的剃刀代码

渲染类

public class Render
{
    public Render()
    {

    }

    public int RenderId { get; set; }
    public string ClientName { get; set; }
    public string Title { get; set; }
    public string JobId { get; set; }
    public string Comment { get; set; }

    public ICollection<Image> Images { get; set; }

    public string ZipFileName
    {
        get { return (ClientName + "-" + Title + "-" + JobId)
                .Replace(" ", string.Empty); }
    }
}

查看模型

public class RenderDetailViewModel
{
    public IEnumerable<Render> AllRenders { get; set; }
    private readonly RenderLibContext _db = new RenderLibContext();

    public void PopulateRenderDetailModel(int id)
    {
        AllRenders = _db.Renders.Include("Images")
            .Where(r => r.RenderId == id)
            .ToList();
    }
}

控制器

public ActionResult Detail(int id=1)
{

    var render = _db.Renders.Include("Images")
                    .Include(r => r.Comments.Select(c => c.CommentImages))
                    .Include("VenueType").Include("ScreenCount")
                    .FirstOrDefault(r => r.RenderId == id);

    var model = new RenderDetailViewModel()
    {
        RenderId = render.RenderId,
        ClientName = render.ClientName,
        Title = render.Title,
        JobId = render.JobId,
        RenderMonth = render.RenderMonth,
        RenderYear = render.RenderYear,
        Comment = render.Comment,
        Venue = render.Venue,
        Mapping = render.Mapping,
        DefaultImageId = render.DefaultImageId

    };

    return View(model);
}

剃刀代码(缩写)

@model RenderLib.ViewModels.RenderDetailViewModel
...
@foreach (var group in Model.Images.Select(i => i.Version).Distinct().ToList())
{
  <a href="?Set=@group">Set @counter</a>
  <a href="/Renders/Download/@Model.RenderId?fn=@Model.ZipFileName">Download</a>
  ...
}
@foreach (var images in Model.Images
.Where(i => i.RenderId == Model.RenderId && i.Version == Request.QueryString["Set"]))
{
   <li data-thumb="/ImageStore/@images.Path">
     <a href="javascript:void(0)">
       <img src="~/ImageStore/@images.Path" />
     </a>
   </li>
}

此行以上的所有内容均正常,但我的计算属性位于错误的位置,我希望它位于我的ViewModel

我知道很多人希望看到有人问这样的问题,以示出他们已经尝试确保我不仅仅是在没有先尝试某些事情的情况下寻求答案,以下是一个例子在我的ViewModel中创建计算属性的众多尝试之一:

查看模型(我的尝试)

public class RenderDetailViewModel
{
    public IEnumerable<Render> RenderById { get; set; }
    private static readonly RenderLibContext _db = new RenderLibContext();

    private readonly Render _model;
    public RenderDetailViewModel(Render r)
    { _model = r; }

    public string ClientName { get { return _model.ClientName; } }
    public string Title { get { return _model.Title; } }
    public string JobId { get { return _model.JobId; } }

    public string ZipFileName
    {
        get { 
            return (ClientName + "-" + Title + "-" + JobId)
                        .Replace(" ", string.Empty); 
        }
    }

    public void PopulateRenderDetailModel(int id)
    {
        RenderById = _db.Renders.Include("Images")
            .Where(r => r.RenderId == id)
            .ToList();
    }
}

这次尝试搞砸了我的控制器并希望我传递一个参数。这不是我的目标。任何帮助将不胜感激。我希望我能够帮助那些可能提供帮助的人。

1 个答案:

答案 0 :(得分:2)

视图模型不应包含任何数据库逻辑。它应该只有简单的属性。此外,您无法在需要回发的任何编辑场景中使用此功能,因为a)您没有无参数构造函数(将抛出异常)并且您的属性没有setter。只需将数据模型中的属性复制到视图模型中,然后在控制器中进行映射(然后就可以删除数据模型中的ZipFileName

public class RenderViewModel
{
  public int RenderId { get; set; }
  public string ClientName { get; set; }
  ....
  public IEnumerable<Image> Images { get; set; }
  public string ZipFileName
  {
    get { return (ClientName + "-" + Title + "-" + JobId)
            .Replace(" ", string.Empty); }
  }
}

控制器

public ActionResult Detail(int id)
{
  var render = db.Renders.Include("Images").Where(r => r.RenderId == id).FirstOrDefault();
  var model = new RenderViewModel()
  {
    RenderId = render.RenderId,
    ClientName = render.ClientName,
    ....,
    Images = render.Images.Select(...), // not sure what your trying to do here
  });
  return View(model);
}

查看

@model RenderViewModel
@Html.DisplayFor(m => m.ClientName)
....
@foreach (var group in renders.Images)
{
  // better to use helpers to generate the link
  @Html.ActionLink("Download", "Download", "Renders", new { ID = Model.RenderId, fn = Model.ZipFileName })
}

注意,在选择与每个渲染相关联的图像时,我对您尝试执行的操作感到困惑。对于每个图像,您生成相同的链接(基于渲染的RenderIdZipFileName)。 Image中是否有属性应包含在路由参数中,以便每个链接下载不同的内容?