Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
559 views
in Technique[技术] by (71.8m points)

c# - 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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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;
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...