Reputation: 10932
Let's presume I have a view for a blog post and I need to come up with a view model for that view. The view displays
If these were just text elements, I'd go with
public PostViewModel
{
public string AuthorName { get; set; }
public DateTime Date { get; set; }
public int NumberOfComments { get; set; }
public IEnumerable<string> Tags { get; set; }
}
However, what if I wanted some of these to be links? Clicking on the author name would take me to the author's profile, clicking on comments would take me to the comments. Now this all of a sudden becomes more challenging.
What are my options here?
ActionLink
inside the view, same for comments (post ID)Out of these only option 4 seems viable, so
public ActionViewModel
{
public string Action { get; set; }
public string Controller { get; set; }
public string Text { get; set; }
public RouteValueDictionary RouteValues { get; set; }
}
and PostViewModel
becomes
public PostViewModel
{
public ActionViewModel AuthorName { get; set; }
public DateTime Date { get; set; }
public ActionViewModel NumberOfComments { get; set; }
public IEnumerable<ActionViewModel> Tags { get; set; }
}
At this point I'm wondering why the framework wouldn't support such a common scenario out of the box. Am I missing something here or is this indeed the way to go?
EDIT: I added the Tags
property to make it more clear why I consider option 2 to be problematic. I can't just have
public IEnumerable<string> Tags { get; set; }
public IEnumerable<int> TagIds { get; set; }
because there is no safe correlation between a tag name and its ID, so I'd have to introduce an object here anyway.
Upvotes: 1
Views: 2943
Reputation: 218732
You can simply add a property for post id and another for author Id and use those.
public PostViewModel
{
public int Id {set;get;}
public int AuthorId { set;get;
public string AuthorName { get; set; }
public DateTime Date { get; set; }
public int NumberOfComments { get; set; }
}
In your view
@model PostViewModel
<p>Post created by @Html.ActionLink(Model.AuthorName,"Details","User"
,new { id=Model.AuthorId},null)</p>
<p>Total @Html.ActionLink(Model.NumberOfComments,"Comments","Post"
,new { postId =Model.AuthorId},null)</p>
Assuming you have a Details
action method in Usercontroller which accepts an id
parameter and Comments action on PostController which accepts a postId
parameter.
If you already have an User/Author view model, you can replace the AuthorId
and AuthorName
in your PostViewModel
with that.
EDIT : As per the question edit.
if you want a collection of Tags, create another little view model for that and use a collection of that type as your property
Here i created a view model for Author as well as you need that in the Author details page (which goes from the author link)
public class BaseVm
{
public int Id {set;get;}
public string Name { set;get;}
}
public class AuthorVm : BaseVm
{
}
public class TagVm : BaseVm
{
}
public PostViewModel
{
public int Id {set;get;}
public AuthorVm Author { set;get;
public DateTime Date { get; set; }
public int NumberOfComments { get; set; }
public List<TagVm> Tags {set;get;}
public PostViewModel()
{
this.Tags = new List<TagVm>();
this.Author = new AuthorVm();
}
}
Now in your view, you should access the author Id/Name like Model.Author.Id
Upvotes: 2