Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's a clean/DRY way to show available operations on user content?

Working on an ASP.NET MVC 3 (Razor) application, that's mainly concerned with UGC (user generated content).

I'm working on a "Q&A" area - where users can ask questions, others can answer, vote, etc.

As such, i'm trying to figure out a clean way to handle the available operations a user can do on any given page, based on their role and other factors.

Take the scenario of the "Question Detail Page" (like this page on Stack Overflow).

Any (authenticated) user can:

  • Vote for question/answer
  • Answer

Question owner can:

  • Edit
  • Delete
  • Mark answer

And so forth.

Now, i have a QuestionViewModel, that is used to display the question and relevant answers for this particular View.

I create it using AutoMapper.

How can i display "stickies" (e.g hyperlinks) on the page, based on the available operations?

My current thinking is:

  • I create an enum: QuestionOperation (Answer, Edit, Disable, Vote, Answer, etc)
  • I add a property of type IEnumerable<QuestionOperation> to my ViewModel
  • I set this property in my action method (HTTP GET), checking if the user is authenticated and the roles they are a part of.
  • I then use an editor template to render out each operation as a hyperlink, using Html.ActionLink

Is that considered a clean approach - or can anyone suggest a better one?

Keeping in mind i am re-using this QuestionViewModel on three pages:

  1. The question detail page
  2. The "Ask a question" page
  3. The "Edit a question" page

So because these operations are page/user dependant, it can't really be done with AutoMapper.

like image 705
RPM1984 Avatar asked Nov 13 '22 22:11

RPM1984


1 Answers

I would setup a separate controller and action which will be returning a partial view containing the necessary links. Then I would use the Html.Action helper to include it from the main view.

Something among the lines:

public class UserLinksController: Controller
{
    // TODO: ctor DI of a repository, etc...

    public ActionResult Index(string questionId)
    {
        string username = User.Identity.IsAuthenticated 
            ? User.Identity.Name : string.Empty;
        var roles = _repository.GetRolesForQuestion(username, questionId);
        var model = Mapper.Map<UserRoles, RolesViewModel>(roles);
        return PartialView(model);
    }
}

and in the corresponding partial you would check the view model and render the necessary links:

@model RolesViewModel
@if(Model.CanEdit)
{
    @Html.ActionLink("Edit", "Edit", "Questions")    
}
@if(Model.CanDelete)
{
    @Html.ActionLink("Delete", "Delete", "Questions")    
}
...

Now somewhere in your main view simply include this action using the Html.Action method:

@Html.Action("Index", "UserLinks", new { questionId = Model.QuestionId })
like image 193
Darin Dimitrov Avatar answered Nov 17 '22 00:11

Darin Dimitrov