Я искал StackOverflow и MSDN и нашел несколько страниц, которые, как я чувствовал, помогли бы мне, но как только я попытался реализовать решения, всегда было что-то немного отличающееся от того, что мне было нужно, поэтому теперь я здесь, после нескольких часов вытягивания волос.
Проблема: у меня есть расчетное свойство в моем классе модели. Имя класса - Render и представляет собой модель для Photo Renderings. Вычисленное свойство будет использоваться как имя для Zip файла, который я собираю вместе в ONE VIEW для пользователя, в зависимости от того, на какой странице Render Detail они находятся. Очевидно, мы не хотим делать это в модели, потому что не каждый взгляд или даже большинство представлений будут использовать его.
Вопрос: Как перенести это вычисляемое свойство в мой ViewModel?
Ниже вы увидите мой текущий и рабочий.
Класс рендера
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/@[email protected]">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();
}
}
Эта попытка накрутила мой контроллер и ожидала, что я передам аргумент. Это не то, что я хотел сделать. Любая помощь будет принята с благодарностью. Надеюсь, я включил все необходимое, чтобы помочь всем, кто может помочь.
Модель представления не должна содержать логики базы данных. Он должен иметь только простые свойства. Кроме того, вы не можете использовать это в любом сценарии редактирования, где вам нужно отправить сообщение, потому что: а) у вас нет конструктора без параметров (вызывается исключение), и у вас нет настроек. Просто скопируйте свойства из вашей модели данных в вашу модель просмотра и сделайте сопоставление в контроллере (а затем вы можете удалить 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 })
}
Заметьте, я смущен тем, что вы пытаетесь сделать, когда выбираете изображения, связанные с каждым рендерингом. Для каждого изображения вы создаете идентичную ссылку (на основе RenderId
и ZipFileName
рендеринга). Есть ли свойство в Image
которое должно быть включено в параметры маршрута, поэтому каждая ссылка загружает что-то другое?
Image
(ваше представление не показывает, что вы пытаетесь делать с коллекцией Image
)
Render
в представлении, почему у вас есть @foreach (var renders in Model.AllRenders)
? Можете ли вы подтвердить, что _db.Renders.Include("Images").Where(r => r.RenderId == id)
возвращает только один Render
, тогда я могу обновить свой ответ.