5
\$\begingroup\$

I have a pretty common issue: I need to know the name of current user and also name of the current controller so I can highlight/disable some links.

Here's some solutions I found by myself:

  1. Get all what's needed inside PartialView.

    I have a PartialView inside my page layout, that takes user name like this:

    @{ var userName = Context.ToContext().GetUser<Agent>().Name; }
    

    And here's the way I take controller name:

    @{ var controllerName = HttpContext.Current.Request.RequestContext.RouteData.Values["controller"].ToString(); }
    

I have some problem with this code, for it is suspected to ruin MVC pattern. I have another solution, which I consider even more stupid.

  1. I've created new controller called like ContextController:

    public class ContextController : BaseController // BaseController is just a facade
    {
        public string GetUserName() {
            return Context.GetUser<Agent>().Name;
        }
    }
    

    Here's the problem: I cannot get controller name with this way, because it will always be like "Context", which is useless for me. And I also get the name on view like this:

    @{ var userName = Html.Action("GetUserName", "Context"); }
    
  2. The last way I figured out is to pass needed strings through ViewData. But I have about 18 controllers and some of 'em have like 3 methods, returning ViewResult. It's not bad design, it's just reality. And I don't actually want to create and pass ViewDataDictionary for every single method, that returns ViewResult. Maybe I could extend my BaseController, so ViewDataDictionary for every page will always have userName and controllerName?

    But here comes another problem: I have whole lot of AJAX in my project, and it seems to me not legit enough to pass unused data every time controller action is called.

If you know of a better solution, I'd be happy to hear it.

\$\endgroup\$

2 Answers 2

5
\$\begingroup\$

You should try creating ViewModel classes - they're simple classes which just have a bunch of properties, and you pass them to the view instead of using ViewData or ViewBag. You can make them all inherit off of a base model which has a bunch of show/hide flags (like user1614543 suggested) or put the flags on individual models (the better choice) which get returned to the views that use those flags. Either way, you can put in sane default values so you only need to set them when you're displaying different data. You can even pass the name of the controller as a string, or use an enum to categorize them.

This will make your markup more readable, and ensure type-safety of your data, which will make working with it easier.

Here's an example, although you'll have to convert it from ASPX to Razor.

\$\endgroup\$
4
\$\begingroup\$

I think it is controller's responsibility to decide what should be visible to user. So it looks to me like a good idea to pass some boolean flags to ViewData dictionary like

VeiwData["IsSomeUserSpecificLinkVisible"] = Context.GetUser<Agent>().Name == "Foo";

And view should just bind those flags to appropriate attributes of controls.

\$\endgroup\$
3
  • \$\begingroup\$ So you want me to write this line for every ViewResult i return? It's like in 22 places arount the project. And what if some day i will also need that Agent Email or Id? That's not very adaptive solution, IMO. \$\endgroup\$ Commented Nov 14, 2012 at 14:32
  • 1
    \$\begingroup\$ You put behaviour like this in a filter and apply it manually to some actions/controllers or globally to all controllers. \$\endgroup\$ Commented Nov 14, 2012 at 14:42
  • \$\begingroup\$ @KristofClaes What kind of filter? Can u plz show some code sample? \$\endgroup\$ Commented Nov 14, 2012 at 15:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.