IIS Rewrite, with the swagger ui giving 404 not found error - swagger-ui

I am hosting Dotnet Core 3.1 project with a Vue js application. For that, I have hosted the vue js static files inside the www-root folder.
I also have a swagger UI in my application.
This is the default web config that I have in the hosted directory.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="dotnet" arguments=".\MyApp.dll" stdoutLogEnabled="false"
stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false" />
</system.webServer>
</configuration>
With this configuration, the swagger ui runs fine without any error.
But I have to add the rewrite logic for the Vue js application, so I have updated the web config with the following configuration.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<rewrite>
<rules>
<rule name="wwwroot-static" stopProcessing="true">
<match url="([\S]+[.](html|htm|svg|js|css|png|gif|jpg|jpeg))" />
<action type="Rewrite" url="wwwroot/{R:1}" />
</rule>
<rule name="empty-root-index" stopProcessing="true">
<match url="^$" />
<action type="Rewrite" url="wwwroot/index.html" />
</rule>
<!--
Make sure you have a <base href="/" /> tag to fix the root path
or all relative links will break on rewrite
-->
<rule name="AngularJS-Html5-Routes" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{REQUEST_URI}" pattern="^/.well-known/openid-configuration" negate="true" />
<add input="{REQUEST_URI}" pattern="^/.well-known/jwks" negate="true" />
<add input="{REQUEST_URI}" pattern="^/api(.*)" negate="true" />
<add input="{REQUEST_URI}" pattern="^/swagger(.*)" negate="true" />
<add input="{REQUEST_URI}" pattern="^/account(.*)" negate="true" />
<add input="{REQUEST_URI}" pattern="^/connect(.*)" negate="true" />
</conditions>
<action type="Rewrite" url="wwwroot/index.html" />
</rule>
</rules>
</rewrite>
<handlers>
<add name="StaticFileModuleHtml" path="*.htm*" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
<add name="StaticFileModuleSvg" path="*.svg" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
<add name="StaticFileModuleJs" path="*.js" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
<add name="StaticFileModuleCss" path="*.css" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
<add name="StaticFileModuleJpeg" path="*.jpeg" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
<add name="StaticFileModuleJpg" path="*.jpg" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
<add name="StaticFileModulePng" path="*.png" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
<add name="StaticFileModuleGif" path="*.gif" verb="*" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="dotnet" arguments=".\MyApp.dll" stdoutLogEnabled="false"
stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false" />
</system.webServer>
</configuration>
With this configuration in the web config, my vue js application runs fine. But then when I go the site: http(s)://[MYWEBAPP]/swagger, it redirects to http(s)://[MYWEBAPP]/swagger/index.html and gives a 404 files not found error.
Configure Service in my startup class looks like this:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
app.UseSwagger();
app.UseSwaggerUI(c =>
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Sample API")
);
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
Trying through the multiple available solutions, I realized that the swagger UI is trying to look for the index.html from the wwwroot, so it is causing the not found error. I am stuck on how to suggest swagger UI to look into the own directory.
What could be the issues with this? What am i missing here? Anyone else also might have this issue?

Related

What is wrong with this URL Redirect code? Multiple query string values

I am getting the strangest behavior from my URL Rewrite code. It is a .NET application and the code is in the config file. All other rewrites are working as expected.
URL to rewrite:
http://www.example.com/projects/offer_details.aspx?artistID=64&projectID=100&recordID=1353&selection=1&salesTypeID=6
The Code:
<rule name="OrderDetails" stopProcessing="true">
<match url="^projects/offer_details.aspx$" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="true">
<add input="{QUERY_STRING}" pattern="artistID=(\d+)" />
<add input="{QUERY_STRING}" pattern="projectID=(\d+)" />
<add input="{QUERY_STRING}" pattern="recordID=(\d+)" />
<add input="{QUERY_STRING}" pattern="selection=(\d+)" />
<add input="{QUERY_STRING}" pattern="salesTypeID=(\d+)" />
</conditions>
<action type="Redirect" url="/OfferDetails/{C:1}/{C:2}/{C:3}/{C:4}/{C:5}" appendQueryString="false" />
</rule>
Here is what I am seeing in Fiddler:
GET /OfferDetails/64?artistID=64&projectID=100&recordID=1353&selection=1&salesTypeID=6
It looks as if it is catching the first param and the page fine but it is ignoring all of the other values and adding the query string even though appendQueryString="false".
This is what it should redirect to:
http://www.example.com/projects/OfferDetails/64/100/1353/1/6
Any ideas? I'm stumped. Restarted the site. Cleared all caches and nada.
Was not able to replicate your issue. It'll be helpful, if you could post your config file.
However, there is another issues I found in the rewrite rule. Your redirect url should be /projects/OfferDetails/{C:1}/{C:2}/{C:3}/{C:4}/{C:5} and not /OfferDetails/{C:1}/{C:2}/{C:3}/{C:4}/{C:5}.
<rule name="OrderDetails" stopProcessing="true">
<match url="^projects/offer_details.aspx$" />
<conditions logicalGrouping="MatchAll" trackAllCaptures="true">
<add input="{QUERY_STRING}" pattern="artistID=(\d+)" />
<add input="{QUERY_STRING}" pattern="projectID=(\d+)" />
<add input="{QUERY_STRING}" pattern="recordID=(\d+)" />
<add input="{QUERY_STRING}" pattern="selection=(\d+)" />
<add input="{QUERY_STRING}" pattern="salesTypeID=(\d+)" />
</conditions>
<action type="Redirect" url="/projects/OfferDetails/{C:1}/{C:2}/{C:3}/{C:4}/{C:5}" appendQueryString="false" />
</rule>

Serilog - Configuring Multiple Sinks in AppSettings

I am trying to wire-up serilog using the app settings package and when I run my program Serlog is complaining it cannot find the RollingFile assembly. I did not have this problem using a single sink but multiple it giving me fits:
<!-- Serilog Configuration -->
<add key="serilog:using:Email" value="Serilog.Sinks.Email" />
<add key="serilog:using:RollingFile" value="Serilog.Sinks.RollingFile" />
<!-- Configure Serilog Email Sink -->
<add key="serilog:write-to:Email"/>
<add key="serilog:write-to:Email.mailServer" value="***" />
<add key="serilog:write-to:Email.toEmail" value="***" />
<add key="serilog:write-to:Email.fromEmail" value="***" />
<add key="serilog:write-to:Email.mailSubject" value="Notification" />
<add key="serilog:write-to:Email.restrictedToMinimumLevel" value="Debug" />
<!-- Configure Serilog RollingFile Sink -->
<add key="serilog:write-to:RollingFile" />
<add key="serilog:write-to:RollingFile.restrictedToMinimumLevel" value="Debug" />
<add key="serilog:write-to:RollingFile.pathFormat" value="C:\Logs\comply360-user-mgmt-{Date}.txt" />
<add key="serilog:write-to:RollingFile.outputTemplate" value="{Timestamp:HH:mm:ss} [{Level}] [{SourceContext}] [{CorrelationId}] {Message}{NewLine}{Exception}" />
You have to use prefix in web.config and in Configuration like this
Web.Config
<!-- Serilog Configuration -->
<add key="email:serilog:using:Email" value="Serilog.Sinks.Email" />
<add key="file:serilog:using:RollingFile" value="Serilog.Sinks.RollingFile" />
<!-- Configure Serilog Email Sink -->
<add key="email:serilog:write-to:Email"/>
<add key="email:serilog:write-to:Email.mailServer" value="***" />
<add key="email:serilog:write-to:Email.toEmail" value="***" />
<add key="email:serilog:write-to:Email.fromEmail" value="***" />
<add key="email:serilog:write-to:Email.mailSubject" value="Notification" />
<add key="email:serilog:write-to:Email.restrictedToMinimumLevel" value="Debug" />
<!-- Configure Serilog RollingFile Sink -->
<add key="file:serilog:write-to:RollingFile" />
<add key="file:serilog:write-to:RollingFile.restrictedToMinimumLevel" value="Debug" />
<add key="file:serilog:write-to:RollingFile.pathFormat" value="C:\Logs\comply360-user-mgmt-{Date}.txt" />
<add key="file:serilog:write-to:RollingFile.outputTemplate" value="{Timestamp:HH:mm:ss} [{Level}] [{SourceContext}] [{CorrelationId}] {Message}{NewLine}{Exception}" />
Startup.cs
Log.Logger = new LoggerConfiguration()
.ReadFrom
.AppSettings("email")
.ReadFrom
.AppSettings("file")
.CreateLogger()
figured it out. i had to remove the rolling file using statement.

How to set up an IIS Rewrite rule for everything except the /api route

I'm setting up a webapi application with an angular front-end. I want to enable html5mode, so the web server needs to have a re-write rule that sends all requests back to the index page.
The problem is the actions in the /api route are matching this rule of course, so none of my REST calls will pass through the rewrite rule.
I'm sure I'm not alone with this problem. Can anyone share the section of the web.config so that my REST service works and html5mode isn't broken?
<system.webServer>
<modules>
<remove name="FormsAuthentication" />
</modules>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
<rewrite>
<rules>
<rule name="Main Rule" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{REQUEST_URI}" matchType="Pattern" pattern="api/(.*)" negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
</system.webServer>

How can I hook up custom email provider in ELMAH?

I've asked this on the elmah group in google groups but am still mystified so I thought I'd throw it out to a larger pool. Here's the original note with my code as it currently stands.
I have ELMAH set up on my MVC 5 application and I want to use a custom email service to send email instead of using the smtp send that is set up by default. (This is an organizational preference.) I've been poking around at it but can't figure out how to do this. My service call is working just fine, but I can't hook it up so that it runs when there is an exception. Any assistance will be greatly appreciated.
What I've got set up is the following:
Web.config (removed non-elmah-related lines):
<?xml version="1.0" encoding="utf-8"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=301880
-->
<configuration>
<configSections>
<sectionGroup name="elmah">
<section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah" />
<section name="errorLog" requirePermission="false" type="Elmah.ErrorLogSectionHandler, Elmah" />
<section name="errorMail" requirePermission="false" type="Elmah.ErrorMailSectionHandler, Elmah" />
<section name="errorFilter" requirePermission="false" type="Elmah.ErrorFilterSectionHandler, Elmah" />
</sectionGroup>
</configSections><appSettings>
...
<add key="elmah.mvc.disableHandler" value="false" />
<add key="elmah.mvc.disableHandleErrorFilter" value="false" />
<add key="elmah.mvc.requiresAuthentication" value="false" />
<add key="elmah.mvc.IgnoreDefaultRoute" value="false" />
<add key="elmah.mvc.allowedRoles" value="*" />
<add key="elmah.mvc.allowedUsers" value="*" />
<add key="elmah.mvc.route" value="elmah" />
</appSettings>
<connectionStrings>
<add name="BFRDPDB" providerName="System.Data.SqlClient" connectionString="blahblah;" />
</connectionStrings>
<system.web>
<compilation debug="true" targetFramework="4.5.1" />
<customErrors mode="Off" defaultRedirect="~/Home/Error">
<error statusCode="404" redirect="~/Home/Error" />
</customErrors>
<httpModules>
<add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" />
<add name="ErrorMail" type="BFRDP.Infrastructure.ErrorMailModule" />
<add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" />
</httpModules>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules>
<add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" preCondition="managedHandler" />
<add name="ErrorMail" type="BFRDP.Infrastructure.ErrorMailModule" preCondition="managedHandler" />
<add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" preCondition="managedHandler" />
</modules>
</system.webServer>
<elmah>
<security allowRemoteAccess="false" />
<errorLog type="Elmah.SqlErrorLog, Elmah"
connectionStringName="BFRDPDB"
applicationName="FarmAnswers.org" />
</elmah>
<location path="elmah">
<system.web>
<httpHandlers>
<add verb="POST,GET,HEAD"
path="elmah.axd"
type="Elmah.ErrorLogPageFactory, Elmah" />
</httpHandlers>
<authorization>
<allow roles="SuperAdmin" />
<deny users="*" />
</authorization>
</system.web>
<system.webServer>
<handlers>
<add name="ELMAH"
verb="POST,GET,HEAD"
path="elmah"
type="Elmah.ErrorLogPageFactory, Elmah"
preCondition="integratedMode" />
</handlers>
</system.webServer>
</location>
</configuration>
And my ErrorMailModule.cs file looks like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Net.Mail;
namespace BFRDP.Infrastructure
{/// <summary>
/// Summary description for ErrorMailModule
/// </summary>
public class ErrorMailModule : Elmah.ErrorMailModule
{
public ErrorMailModule()
{
}
protected override void SendMail(MailMessage mail)
{
if (mail == null)
throw new ArgumentNullException("mail");
// Code to send email here through internal provider
}
}
}
My error is indeed logged in the database, but the code to send the email is never reached.
What am I doing wrong?
Added the errorMail settings in the section of my web.config and the app was able to get to my custom module:
<elmah>
<security allowRemoteAccess="false" />
<errorLog type="Elmah.SqlErrorLog, Elmah" connectionStringName="BFRDPDB" applicationName="FarmAnswers.org" />
<errorMail
from="elmah#example.com"
to="admin#example.com"
subject="..."
priority="Low"
async="true"
smtpPort="25"
smtpServer="smtp.example.com"
useSsl="true"
userName="johndoe"
password="secret"
noYsod="true" />
</elmah>

ASP.Net MVC + Facebook oAuth + rewrite rule cause response_type=code

I'm experimenting an issue when I create some rewrite rule into my ASP.Net app.
When I activate this rule :
<rewrite>
<rules>
<rule name="Main Rule" stopProcessing="true">
<match url="^.*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{REQUEST_URI}" matchType="Pattern" pattern="^/api/" negate="true" />
<add input="{REQUEST_URI}" matchType="Pattern" pattern="^/token" negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
My application will try to authenticate through Facebook with response type : code instead of token.
When I disable It, I'm well redirecting with response_type = token
Is there anybody who had to deal with it ?
thank you.
I Found the solution.
The problem was that my rule was catching the facebook response. The owin Context was attempting to catch the code and then ask facebook to retrieve the token. Bu as my rule was done like previously, it was my App who catched the facebook code...
I had to change my rule in order to not treat signin requests like this:
<rewrite>
<rules>
<rule name="Main Rule" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
<add input="{REQUEST_URI}" matchType="Pattern" pattern="^/api/" negate="true" />
<add input="{REQUEST_URI}" matchType="Pattern" pattern="^/signin" negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
Hope this will help.
Regards,

Resources