Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET Core 2 - ReSharper "Create Razor View" adds new view to Pages folder

I've started trying out new ASP.NET Core 2 for building an MVC Web App, and it looks good so far...

Except that when I create Views from my controller actions, ReSharper creates them in a Pages folder, rather than the Views folder (where I generally like to keep my Views ;-) )

resharper create razor view view in pages folder

ReSharper doesn't behave this way for regular ASP.NET Web Apps (not core), it puts the views in the correct view folder, so this looks to be to do with Core / Core 2.

What is resharper using to decide where to create the view?

How can I change this behavior so that it creates the views in the traditional location?

like image 474
Erresen Avatar asked Sep 27 '17 19:09

Erresen


Video Answer


2 Answers

I think this is a bug in Resharper and I'm suspecting it might be related to the new Razor Pages Apps .net core 2 team just released.

So, perhaps it would be better for you to fill an issue on Reshaper's Bug Tracking System.

However, I've managed to setup a workaround. I'm sharing the steps here, just in case you need to fix this ASAP and when JetBrains fixes the issue - if it finally is an issue :) - you can remove this patch.

  1. Install the nuget package for Jetbrains Annotations.

    Install-Package JetBrains.Annotations
    
  2. Create a .cs file on the root of your asp.net core project - I've named it ResharperConfig.cs - with the following content:

    using JetBrains.Annotations;
    
    [assembly: AspMvcMasterLocationFormat("~/Views/{1}/{0}.cshtml")]
    [assembly: AspMvcViewLocationFormat("~/Views/{1}/{0}.cshtml")]
    [assembly: AspMvcPartialViewLocationFormat("~/Views/Shared/{0}.cshtml")]
    [assembly: AspMvcAreaMasterLocationFormat("~/Areas/{2}/Views/{1}/{0}.cshtml")]
    [assembly: AspMvcAreaViewLocationFormat("~/Areas/{2}/Views/{1}/{0}.cshtml")]
    [assembly: AspMvcAreaPartialViewLocationFormat("~/Areas/{2}/Views/Shared/{0}.cshtml")]
    
  3. Build your project and restart VS. (this was important for me).

  4. When you reopen the solution, R# will recognize the locations for the views. Now you can go and create views from the actions the way you're used to.

Resharper issue

Hope this helps!

like image 185
Karel Tamayo Avatar answered Oct 16 '22 06:10

Karel Tamayo


This still applies to the ASP.NET Core Web App (Model-View-Controller) .NET 6 template installed with VS 2022. R# generates views in \Pages by default, which is the wrong location anyway.

With the ResharperConfig.cs (as described above) now R# creates the views in the right place, assuming the View's parent folder exists.

My entity centered Clean Architecture configuration:

using JetBrains.Annotations;

[assembly: AspMvcMasterLocationFormat("~/Views/{1}/{0}.cshtml")]
[assembly: AspMvcViewLocationFormat("~/{1}/Views/{0}.cshtml")]
[assembly: AspMvcPartialViewLocationFormat("~/Views/Shared/{0}.cshtml")]
[assembly: AspMvcAreaMasterLocationFormat("~/Areas/{2}/Views/{1}/{0}.cshtml")]
[assembly: AspMvcAreaViewLocationFormat("~/Areas/{2}/Views/{1}/{0}.cshtml")]
[assembly: AspMvcAreaPartialViewLocationFormat("~/Areas/{2}/Views/Shared/{0}.cshtml")]

This [assembly: AspMvcViewLocationFormat("~/{1}/Views/{0}.cshtml")] makes sure R# generates views in this location: \<Controller>\Views\<Action>.cshtml

You should combine that with a IViewLocationExpander to instruct .NET to also look in the same location to find the views while rendering them:

using Microsoft.AspNetCore.Mvc.Razor;

public class CleanArchViewLocationExpander : IViewLocationExpander
{
    public void PopulateValues(ViewLocationExpanderContext context)
    {
    }

    public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations)
    {
        return viewLocations.Select(l => l.Replace("/Views/{1}/", "/{1}/Views/"));
    }
}

Which you then register in Program.cs like this:

builder.Services.Configure<RazorViewEngineOptions>(
    options =>
    {
        options.ViewLocationExpanders.Add(new CleanArchViewLocationExpander());
    });

Happy coding!

like image 24
Raymond Brink Avatar answered Oct 16 '22 05:10

Raymond Brink