Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Working with IViewLocationExpander in mvc

I want to render views from a custom location, so for that I have implemented the IViewLocationExpander interface in a class. I have registered the same class in Startup class as follows.

Startup Class

public void ConfigureServices(IServiceCollection services)
{
    … 
    //Render view from custom location.
    services.Configure<RazorViewEngineOptions>(options =>
    {
        options.ViewLocationExpanders.Add(new CustomViewLocationExpander());
    });
    … 
}

CustomViewLocationExpander Class

public class CustomViewLocationExpander : IViewLocationExpander
{
    public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations)
    {

        var session = context.ActionContext.HttpContext.RequestServices.GetRequiredService<SessionServices>();
        string folderName = session.GetSession<string>("ApplicationType");

        viewLocations = viewLocations.Select(f => f.Replace("/Views/", "/" + folderName + "/"));


        return viewLocations;
    }

    public void PopulateValues(ViewLocationExpanderContext context)
    {

    }
}

And, finally, my application’s views are organized as follows:

View folder structure

My issue: If I access the Views/Login view from the ViewsFrontend folder from the following URL:

http://localhost:56739/trainee/Login/myclientname 

But then immediately change the URL in the browser to:

http://localhost:56739/admin/Login/myclientname

In this case, it still refers to the ViewsFrontend folder, even though it should now refer to the ViewsBackend folder, since URLs beginning with trainee should refer to the ViewsFrontend folder, while those beginning with admin should refer to the ViewsBackend folder.

Further, after changing the URL in the browser, it only calls the PopulateValues() method, but not the ExpandViewLocations() method.

How can I reconfigure this class to work for this other folder?

like image 664
XamDev Avatar asked Sep 13 '16 13:09

XamDev


1 Answers

PopulateValues exists as a way to specify parameters that your view lookup would vary by on a per-request basis. Since you're not populating it, the view engine uses cached values from an earlier request.

To solve this, add your ApplicationType variable to the PopulateValues() method and the ExpandValues() method should get called whenever that value changes:

public class CustomViewLocationExpander : IViewLocationExpander
{
    public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations)
    {
        string folderName = context.Values["ApplicationType"];
        viewLocations = viewLocations.Select(f => f.Replace("/Views/", "/" + folderName + "/"));

        return viewLocations;
    }

    public void PopulateValues(ViewLocationExpanderContext context)
    {
        var session = context.ActionContext.HttpContext.RequestServices.GetRequiredService<SessionServices>();
        string applicationType = session.GetSession<string>("ApplicationType");
        context.Values["ApplicationType"] = applicationType;
    }
}
like image 81
Pranav Avatar answered Sep 29 '22 07:09

Pranav