asp.net mvc area not working on iis - iis

I crated area/modular MVC5 application according to this tutorial:
This
it worked perfectly on local. but i got 404 error, when i deployed project on iis and clicked on specified area link.
and i didn't find any solution for that.
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /Sale
and this is my action links which are perfectly working on local run:
#Html.ActionLink("Sale","Index","Sale",new { Area="Sale"},null)
edited:
public class SaleAreaRegistration:AreaRegistration
{
public override string AreaName
{
get
{
return "Sale";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Sale_default",
"Sale/{controller}/{action}/{id}",
new { controller = "Sale", action = "Index", id = UrlParameter.Optional },
new string[] { "MVCPluggableDemo.Controllers" }
);
}
}
attention: according to the tutorial which i said in first line. i created my module project in another virtual project in solution(the real path is in area folder of main project like"~/ProjectName/Areas/"). but i think the publisher does't understand it...because i don't see any of my module views in deployed path.
its better to completing my help request by this obvious question:
How to deploy MVC project include areas, and the modules which are in areas folder?

Its simply obvious:
Check your page directory. The server cannot locate your the file,
it maybe in different folder.
Also try to Check this.

the main Reason of my problem was this:
VisualStudio doesn't include my Area folder, in publish path..why? i don't know
Solution: no solution yet!..but i added my module dll inside bin folder manually. and created my areas folder and his modules projects solution(dlls' are not not necessary) in main published solution, manually to ..
finally it worked, but i dont thing is the standard solution

Related

Blazor Component (in library) and JSInterop

I've created a Blazor Component within a full Blazor project and all works well.
However, when I move this component to it's own Razor Class Library project, I am now getting an error that I cannot use JSInterop until a connection with the server is made. I am running my code in the OnAfterRenderAsync() method.
I had to alter the code a little when I made the change.
In a full Blazor project, JSInterop is provided for you with DI in the Startup class. But this is not the case with a calss library.
So instead of "#inject JSInterop js" in the page, I had to set it up like this -
private IJSRuntime js { get; set; }
protected override void OnInitialized()
{
js = ScopedServices.GetRequiredService<IJSRuntime>();
}
From the sketchy details available on the web, I'm assuming this gets the service from the Parent project.
Using debugging, I can see that js is NOT null. It does seem to have been set to a valid object.
Can anyone point me in the right direction?
The server pre-renders, so your code will run before there is a client connection to the server. When rendering in OnAfterRenderAsync you should only use IJSRuntime when the firstRender parameter is true, or any point after that, but never before.
Found the solution to my problem and it has rendered my initial question irrelevant.
When I copied my component to it's own class library project, it would not compile. It gave me an error on the line #inject JSInterop js.
This led me to believe that it didn't know how to inject this as it is not set during the Startup of the project, as it is in a Blazor app.
So I cobbled together the code to get a reference via ScopedServices.GetRequiredService().
This did create an object but did not have _clientProxy set which contains the connection to the server.
So digging round I managed to find a complete component library example project at BlazorHelp Website
This did have the JSInterop injected in the Blazor file. So I reverted my code back to the original code that worked in the full project and tried to compile. It gave me the same error. So I deleted the #inject JSInterop js line and typed it in again.
IT RECOGNIZED IT!!!
It still failed to compile, not recognizing a custom type (Pivot) and asking whether I had included a reference to it.
[CascadingParameter] public Pivot OwnerPivot { get; set; }
I deleted the word Pivot and retyped it and, voila, it compiled.
So it looks like there some sort of error in VS2019 or the razor compiler, where deleting code in the source file and re-entering caused it to recognize and compile.

nopCommerce store with a custom plugin web deploy issue

NopCommerce version: 3.9
I've designed a web store using NopCommerce 3.9. Any code I added is in a plugin.
The store uses a front page that can be found in the plugin. It relies on a route called 'home' in a RouteProvider class in the plugin. It does not complain about that route, instead it complains about a route named 'RegisterVendor' found in the same file. Here are both routes
routes.MapRoute("home",
"",
new { controller = "AoiVendorsHome", action = "Index" },
new[] { "Nop.Plugin.Other.AoiVendors.Controllers" });
routes.MapRoute("RegisterVendor",
"register/designer",
new { controller = "AoiExchange", action = "RegisterVendor" },
new[] { "Nop.Plugin.Other.AoiVendors.Controllers" });
The plugin installs properly and everything works exactly as expected on my local machine.
The problem is after deploying to the web it can't find the route. Here is a imgur link, follow it to see the error
Restarting the server fixes the error for a while, but it does eventually come back. It also comes back any time I redeploy without restarting the server afterwards.
Does anyone have any ideas?
Thank You.
The "HomePage" route of nopCommerce is registred this way
//home page
routes.MapLocalizedRoute("HomePage",
"",
new { controller = "Home", action = "Index" },
new[] { "Nop.Web.Controllers" });
Check your load order: If your registration does not hit first, remove nopCommerce "HomePage" route and add yours or add yours first using the Priority property of IRouteProvider.
MVC uses the route that first matches the request.
Regarding the deployment problem, make sure your plugin is deployed to ~/Plugins/{yourPluginFolder} and not the bin folder of Nop.Web. Plugin in ~/bin folder can be loaded but without guarantee.
I was able to fix the issue by selecting the 'Remove additional files at destination' checkbox under file publish options on the settings tab in the publish popup dialog in visual studio. I imagine an older file was not being overwritten and was causing problems.

Accessing an IIS Virtual Directory from Dotnet Core

I'm building a Dotnet Core web app that needs to allow the Windows-Authenticated user to browse through the connected virtual directories and view and select files hosted there.
Is there a way for a Dotnet Core application to access a virtual directory? And barring that, is there a way for a regular Dotnet application to do it?
It is possible to do so. I've been working on this thing for two weeks now, looked everywhere to get an answer. Here is how I did it.
You will need to add in the configure app.UseFileServer() in the Configure method of the Startup.cs
app.UseFileServer(new FileServerOptions
{
PhysicalFileProvider("\\\\virtualPath\\photos\\wait\\"),
RequestPath = new PathString("/AROULETTE"),
EnableDirectoryBrowsing = true
});
How does this work?
The way it is set up, you would enter http://localhost:5000/AROULETTE
and it would open the virtual path provided in the PhysicalFileProvider in the browser. Of course this is not what I actually wanted.
I needed to create a directory and copy files into the virtual directory with C#.
Once I had the FileServer setup, I tried something like this which does not work.
if(!Directory.Exists("/AROULETTE/20170814"))
{
Directory.Create("/AROULETTE/20170814")
}
of course, neither does this
var path = Path.Combine("http://localhost:5000/", "AROULETTE/20170814")
if(!Directory.Exists(path)
{
Directory.Create(path)
}
Instead, you just use the actual virtual path of the folder.
if(!Directory.Exists("\\\\virtualPath\\photos\\wait\\20170814"))
{
Directory.Create("\\\\virtualPath\\photos\\wait\\20170814")
}
Thus UseFileServer is used to create a "bridge" between the application and the virtual folder the same way that you would create a virtual directory with ASP.Net 4.5
Hope this can help some people because most of the answers about this topic were not clear at all.

How do you tell Nancy to redirect to a URL inside a virtual directory?

I'm running a Nancy application in a Virtual Directory on my development machine and I've got static content working but if the module redirects the browser then the URL being sent back is incorrect.
If the result is:
return new RedirectResponse("/");
Then the browser redirects to http://localhost/ rather than the root of the virtual directory.
If I try
return new RedirectResponse("~/");
I get taken to http://localhost/MyVirtualDirectory/action/~/ which at least includes the virtual directory, but the rest is screwed up.
I should point out that the module is created like this...
public abstract class ActionRootModule : NancyModule
{
protected ActionRootModule() : base("/action/") { }
}
public class SendEmailModule : ActionRootModule
{
public SendEmailModule()
{
// Parts missing for brevity....
Post["/send-email/"] = o => PostSendEmail(o);
}
private dynamic PostSendEmail(dynamic o)
{
// Do stuff...
return new RedirectResponse("~/");
}
}
What is the correct way of telling Nancy to redirect to a specific URL inside a virtual directory?
I'm running Visual Studio on Windows 7 and IIS 7.5 (not IIS Express - as I have incoming traffic from third parties making callbacks)
This won't be a issue on production as the production deployment won't be in a virtual directory.
There are two ways to solve this.
1) Use return Response.AsRedirect("~/");
2) Use return new RedirectResponse(Context.ToFullPath("~/"));
The first option is just a convenient wrapper around the second so either way yields the same result (https://github.com/NancyFx/Nancy/blob/85dfe8567d794ff3e766521a9fa0891832d4fc8a/src/Nancy/FormatterExtensions.cs#L51). The call to ToFullpath() is what corrects the /~/ you saw in your redirected URL.

Why am I getting "A route named 'swagger_docs' is already in the route collection" after I publish my API App?

After publishing my API App I'm getting the yellow error screen of ASP.NET. The error message says "A route named 'swagger_docs' is already in the route collection".
How can I fix this?
This is not related to API Apps per se but more around Web API. What triggers the error is pretty simple:
You publish the API App which is based on Web API.
You discard your project and start working on a new API App based on Web API
You want to publish the new API App instead of the old API App you created at step 1.
You select the API App during "Publish.." and you get the publishing profile of the existing API App we deployed at step 1.
You deploy using Web Deploy and the publishing profile, the new API App on top of the old one.
That will trigger the issue I've explained before. That happens because there are two routes being registered by Swashbuckle when you try to start the app. One of the old one and one of the new one. That's because the old files are still present at the destination.
To solve this, during Web Deploy, click on the Settings tab and then expand the "File Publish Options". There is a checkbox there, called "Remove additional files from destination". This will fix the issue as it will only leave the files you deploy at the destination and not the old ones as well.
Hope it helps.
What if it happens when trying to debug the app locally ?
This happened for me, and the reason was, I renamed my assembly name. So the bin folder had two dlls for the same project with different names which caused this error. Once I deleted the old named dll all is well. Hope this helps.
This happens because You probally are configuring you route in your WebApiConfig class and SwaggerConfig class, as explained below:
WebApiConfig file:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
SwaggerConfig.Register();
}
}
SwaggerConfig file:
using Swashbuckle.Application;
[assembly: PreApplicationStartMethod(typeof(SwaggerConfig), "Register")]
namespace NEOH.Api
{
public class SwaggerConfig
{
public static void Register()
{
What you should do is remove the assembly call on SwaggerConfig file.
It should work.
My Solution & Cause:
I had the same problem when I renamed NamesSpaces,Refactored,etc.
After reading what everyone else did here's what I tried:
Cleaned the Solution in Visual Studio
Cleaned the Bin folder manually
Checked the nameSpace in the Project Properties (copied it just in case) >> Build tab >> Scrolldown to Output and ensure the XML documentation file is correct. You will need this name later.
Opened up: SwaggerConfig.cs >> fixed the name space in here (copy,paste) c.SingleApiVersion("vX","NameSpace")
Scrolled down until I found: GetXmlCommentsPath() copied and pasted the correct name space in the .xml file path.
Ran, smoke tested, finished this post.
My issue was that I was referencing another project that had the Swashbuckle extension.
Here is how I kept both projects without changing the anything in project that was referenced:
Remove the routes created by the project referenced under SwaggerConfig.cs > Register right before GlobalConfiguration.Configuration.EnableSwagger(...).EnableSwaggerUi(...);:
// Clears the previous routes as this solution references another Swagger ASP.NET project which adds the swagger routes.
// Trying to add the Swagger routes more than once will prevent the application from starting
GlobalConfiguration.Configuration.Routes.Clear();
Then, the application will be able to start, but you will see the operations/functions that are in both projects. To remove the operations from the project being referenced...
Create the following class
using Swashbuckle.Swagger;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http.Description;
namespace yournamespace.Models
{
/// <summary>
/// This class allows to manage the Swagger document filters.
/// </summary>
public class SwaggerCustomOperationsFilter : IDocumentFilter
{
/// <summary>
/// Applies the Swagger operation filter to exclude the Swagger operations/functions
/// that are inherited by the other Swagger projects referenced.
/// </summary>
///
/// <param name="p_swaggerDoc">Swagger document</param>
/// <param name="p_schemaRegistry">Swagger schema registry</param>
/// <param name="p_apiExplorer">Api description collection</param>
public void Apply(SwaggerDocument p_swaggerDoc, SchemaRegistry p_schemaRegistry, IApiExplorer p_apiExplorer)
{
IEnumerable<ApiDescription> externalApiDescriptions = p_apiExplorer.ApiDescriptions
.Where(d => d.ActionDescriptor.ControllerDescriptor.ControllerType.Module.Name != GetType().Module.Name);
IEnumerable<int> externalApiDescriptionIndexes = externalApiDescriptions
.Select(d => p_apiExplorer.ApiDescriptions.IndexOf(d))
.OrderByDescending(i => i);
IEnumerable<string> externalPaths = externalApiDescriptions.Select(d => $"/{d.RelativePathSansQueryString()}");
foreach (string path in externalPaths)
{
p_swaggerDoc.paths.Remove(path);
}
foreach (int apiDescriptionIndex in externalApiDescriptionIndexes)
{
p_apiExplorer.ApiDescriptions.RemoveAt(apiDescriptionIndex);
}
}
}
}
And add the following in SwaggerConfig.cs > Register > GlobalConfiguration.Configuration.EnableSwagger(...)
c.DocumentFilter<SwaggerCustomOperationsFilter>();
Alternative cause of this problem:
Seems like a lot of people have this issue resolved by deleting their "bin" and "obj" folders as per the other answers.
However the cause of the issue might be that you are configuring your Swagger Config in a referenced project, as per this comment: https://github.com/domaindrivendev/Swashbuckle/issues/364#issuecomment-226013593
I received this error when one project with Swagger referenced another
project with Swagger. Removing the reference fixed the problem.
This caused me to split some core functionality out into a Third project that both of my API's could reference, rather than them referencing each other.

Resources