Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Abstraction layer between Controller and View

I am trying to create another layer between my controller and my view so that I can pass different versions of a view to a user based on their "client ID" which would be the company to which they belong.

I have the following code:

public class HomeController : Controller
{
    //
    // GET: /Home/
    public ActionResult Index()
    {
        // set client
        var client = new Client();
        client.Id = Guid.NewGuid();
        client.Name = "Foo";

        // set user
        var user = new User();
        user.Id = Guid.NewGuid();
        user.ClientId = client.Id;
        user.Name = "Foo";

        return ViewRenderer.RenderView("AddComplete", client);
    }
}

My ViewRenderer class looks like this:

public static class ViewRenderer
{
    public static ViewResult RenderView(string view, Guid clientId)
    {
        string viewName = GetViewForClient(view, clientId);
        return Controller.View(view);
    }

    public static string GetViewForClient(string view, Guid clientId)
    {
        // todo: logic to return view specific to the company to which a user belongs...
    }
}

The problem is, the line return Controller.View(view); in RenderView(string view, Guid clientId) gives me the error:

System.Web.Mvc.Controller.View()' is inaccessible due to its protection level

I am interested to know how I can resolve this error or if there is a better way to do what I am trying to do, which is to display different versions of a view which are specific to the respective company to which a user belongs.

Edit: Another option I was kicking around in my head...

Is there a way to override the View() method such that I can prepend it with a directory name, for example, a user who belongs to "Acme Co." would call the same controller action as everyone else like View("MyView") but the method would actually be calling View("AcmeCo/MyView") however, I don't actually write that code in my controller, it's just derived from the user's client ID property.

like image 892
user1477388 Avatar asked Apr 13 '26 23:04

user1477388


1 Answers

You can just replace the view engine instead of adding another abstraction.

Write your own View engine (here is how to start off with a RazorViewEngine)

public class ByIdRazorViewEngine : RazorViewEngine
{
   protected override IView CreateView(ControllerContext controllerContext, 
        string viewPath, string masterPath)
{
    var id = // get something from controller context controllerContext
    var newViewPath = CalculateViewPathFromId(id);

    return base.CreateView(controllerContext, newViewPath, masterPath);
}

And register it in Global.asax.cs:

protected void Application_Start()
{
    ViewEngines.Engines.Clear();

    ViewEngines.Engines.Add(new ByIdRazorViewEngine());
}
like image 103
Yishai Galatzer Avatar answered Apr 15 '26 14:04

Yishai Galatzer



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!