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 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?
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.
Install the nuget package for Jetbrains Annotations.
Install-Package JetBrains.Annotations
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")]
Build your project and restart VS. (this was important for me).
Hope this helps!
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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With