Opening Default document on IIS - iis

I've a deployed ASP.NET Web API with a website on the same folder that consume it.
When I type the URL on the Browser such as http://domain.com/ it returns a 404, but if I type http://domain.com/index.html it works!
I wanna know if there's a way to configure it on Web API route, define a default route for it, redirecting to my http://domain.com/index.html when I type http://domain.com/
I've tried ti put this on Web.Config without success:
<defaultDocument enabled="true">
<files>
<add value="/index.html" />
</files>
</defaultDocument>
Also, I set up my IIS to only accept index.html default document. no success =/
Any ideas?

I'm not sure if this is the best way to achieve this, I just edited my RouteConfig.cs such this:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "index.html"
);
}
}
Now I can get http://domain.com works perfectly!
I'd love If anyone have a best way to achieve this!

Well, It is situational, for what you are doing that is fine.
I have done things like:
routes.IgnoreRoute("");
I typically still end up with problems when the default mvc portion of web api is hit and so for me I end up doing this
public ActionResult Index()
{
string filePath = Server.MapPath("~/contact.html");
if (System.IO.File.Exists(filePath))
{
return File(filePath, "text/html");
}
return View();
}

Related

Url scheme based link does not seem to work in Blazor MAUI

I am building an app with .NET MAUI and Blazor, that initially targets iOS, but should also support Android, in a next release.
I have, in my Info.plist file added an entry myapp in the CFBundleURLSchemes array. And I use this as a redirect uri from our web portal (open in app, with the href myapp://settings/profile).
What happens, is that iOS comes and asks confirmation if that link can be opened with my app. (see screenshot).
But it just opens the app to the page that was previously open. It does not navigate to the Blazor page that is registered with the #page "/settings/profile" directive.
Is this something that is not supported? Or do I have to add something around the routing, here?
Current logic
With the following code in AppDelegate (for iOS), I can intercept that call and access the requested Url from that scheme-link.
public override bool OpenUrl(UIApplication application, NSUrl url, NSDictionary options)
{
AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(url);
if (url?.Scheme?.Equals(myScheme, StringComparison.InvariantCultureIgnoreCase) ?? false)
{
var pageUrl = url.ToString().Replace($"{myScheme}://", "");
PageSettings.RequestedUri = pageUrl; // This is the static class/var I want to leverage in BlazorWebView
return base.OpenUrl(application, new NSUrl( pageUrl), options);
}
return base.OpenUrl(application, url, options);
}
However, I don't seem to find out how I can enforce the BlazorWebView to navigate to the right uri.
As I know, there is no way to do this currently with MAUI Blazor.
Refer to the documentation maui-blazor documentation, the .NET MAUI Blazor hybrid project template isn't a Shell-based app.
If you want to route to #page "/settings/profile", you could describe some information about where to go in AppDelegate, then set some staic and launch a simple page (MAUI PAGE), get the value and show the Blazor page.
public override bool OpenUrl (UIApplication app, NSUrl url, string sourceApp, NSObject annotation){
if (url.BaseUrl.Host.Equals ("app.myapp.io")) {
UIViewController page = new TargetPage().CreateViewController();
}
return true;
}
Set the homepage to your needs
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:BlazorDemo"
x:Class="BlazorDemo.TargetPage"
BackgroundColor="{DynamicResource PageBackgroundColor}">
<BlazorWebView x:Name="blazorWebView" HostPage="wwwroot/profile.html">
<BlazorWebView.RootComponents>
<RootComponent Selector="#app" ComponentType="{x:Type local:Main}" />
</BlazorWebView.RootComponents>
</BlazorWebView>
</ContentPage>

Miniprofiler.MVC5: "profiler/results" 404 not found when deployed on IIS

To use Miniprofiler in an MVC 5 application, I followed all the steps mentioned in MiniProfiler for .NET Documentation for ASP.NET
with these differences in Global.aspx:
protected void Application_Start()
{
MiniProfiler.Configure(new MiniProfilerOptions
{
Storage = new MemoryCacheStorage( new System.TimeSpan(1,0,0) ),
ResultsAuthorize = request => {return true;},
// The rest of the options go here
.
.
}
.AddViewProfiling()
);
}
protected void Application_BeginRequest()
{
// For all requests, not only local
MiniProfiler.StartNew();
}
and in Config:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
<!-- hendlers go here as described in the documentation -->
...
</system.webServer>
The rest is identical to the documentation.
The profiler works locally as expected. But when deployed on Windows server 2016 IIS 10, I get 404 not found error for "profiler/results", and when I navigate to "profiler/results-index", an empty table is displayed with headers only, i.e. no rows for results.
Those images are from the browser using Inspect:

mvc 5 controlling authorization for entire controller or entire view folder

I have a mvc 5 application with a product controller and a corresponding view folder for all product related views. I'd like to make this entire thing only accessible to user with username "admin" instead of manually assigning a tag [Authorize(Users = "admin")] on top of every controller method. I tried to add a new web.config in Product views folder with the following content, but didnt work.
<configuration>
<system.web>
<authorization>
<allow users="admin"/>
<deny users="*"/>
</authorization>
</system.web>
</configuration>
Is this possible to achieve at all if yes how?
thanks in advance
The AuthorizeAttribute can be added both on a specific method and on the controller class. The second will affect every action method in that controller.
[Authorize(Users = "admin")]
public class AdminController
{
public ActionResult Index() { ... }
}
If you want to use Web.config you must remember that IIS will load the Web.config file based on the URL without any knowledge of Views. So if the URL is http://server/Products/Something then you must place your configuration file in a folder called Products in the application root. Alternatively you can use <location path="/Products"> in your root Web.config file.

Deny file access but server properly in IIS

I have a js file that includes in the master page.
I want to deny the file access when user type the direct link in the browser address bar.
I've tried the URL filtering IIS,like:
<security>
<requestFiltering>
<denyUrlSequences>
<add sequence="Scripts/Foo/bar.min.js" />
</denyUrlSequences>
</requestFiltering>
</security>
This does work, when i type 'localhost://blah/Scripts/Foo/bar.min.js' I get blocked.
but the page whitch need this js file can not render.
Does anyone have a workaround? Thanks in advance!
I finnaly found this.
and added these sections to web.config:
<security>
<requestFiltering>
<filteringRules>
<filteringRule name="protectjs" scanUrl="true" scanQueryString="true">
<scanHeaders>
<clear />
<add requestHeader="Accept" />
</scanHeaders>
<appliesTo>
<clear />
<add fileExtension=".js" />
</appliesTo>
<denyStrings>
<clear />
<add string="text/html" />
</denyStrings>
</filteringRule>
</filteringRules>
</requestFiltering>
</security>
It works at present, though I know this way is not that reliable.
Not 100% sure but I don’t think there is a way to do this. When browser renders your page it actually sends the same request to the server as the one you do when you manually type in JS file in the browser.
IIS doesn’t have means to distinguish requests you make and the one browser makes in the background while processing your page.
One thing that might work is
adding some kind of ID to your JS file like this Scripts/Foo/bar.min.js?ID=E3CF305B-4444-E011-8FD2-1CC1DEE89A7F
ID is time limited and works only 20 seconds or so after it’s created (enough time for browser to load the page)
creating custom handler that will parse ID and decide if server should return the request or not
So when someone types Scripts/Foo/bar.min.js handler will reject the request but it will also reject request when expired ID is used.
However this is most probably going to be difficult to maintain and also performance intensive for your server.
If you want to hide your JS file why not obfuscate it.
Use HttpModule and Check for HttpContext.Current.Request.UrlReferrer. it will always be null for direct access to the .js file.
public class JSAccessModule : IHttpModule
{
public void Init(System.Web.HttpApplication Appl)
{
Appl.BeginRequest += new System.EventHandler(Rewrite_BeginRequest);
}
public void Rewrite_BeginRequest(object sender, System.EventArgs args)
{
//Block if direct Url is accessed
if (HttpContext.Current.Request.UrlReferrer == null)
{
HttpApplication App = (HttpApplication)sender;
string path = App.Request.Path;
string strExt = System.IO.Path.GetExtension(path);
if (strExt == ".js")
{
HttpContext.Current.Response.Redirect("~/AccessDenied.html");
}
}
}
public void Dispose() { }
}

URL Rewrite HTTP to HTTPS but now backwards

I have the following UrlRewrite code to change from http to https in the url but now I need it to change from https back to http.
For example when I redirect back from the Account/Logon page to the homepage.
Here are my rewriting rules:
<rewrite>
<rules>
<rule name="RequiresHTTPS-Redirect" stopProcessing="true">
<match url="(.+)" />
<conditions>
<add input="{HTTPS}" pattern="off" />
<add input="{RequiresHTTPS:{R:1}}" pattern="(.+)" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{C:1}"
appendQueryString="true" redirectType="Found" />
</rule>
</rules>
<rewriteMaps>
<rewriteMap name="RequiresHTTPS">
<add key="Account/LogOn" value="Account/LogOn" />
</rewriteMap>
</rewriteMaps>
</rewrite>
Put the logic to redirect back to the non-https page in the login page itself. The problem with redirecting from https to http is that the browser is still going to initiate an ssl connection first to the https url before it can get the redirect, so it's somewhat pointless.
There's a couple of scenarios here:
1. All content is protected by web forms <authorization>:
Your users are hitting the logon page because they've browsed to a part of the site that is protected using the <authorization> element. If this is the case you'll have a return URL passed to you in the query string: ReturnUrl. You can redirect users back to whence they came without SSL using:
return Redirect("http://" + Request.Url.Host + returnUrl);
2. Users have to logon to enable additional features:
Your users are clicking on the Logon link to enable some extra functionality that is being trimmed out on your pages if they aren't logged in. For example being able to post forum messages or view premium content.
In this case you could track where they've been before landing on the logon page. This example is based on the template application that you get with Visual Studio 2010 when you create a new MVC3 application (which you may have used as a template for your project).
In that sample application every page uses a master page Site.Master. Site.Master does a Html.RenderPartial("LogOnUserControl") to render the logon link on every page. Open the LogOnUserControl.ascx and change the code that renders the logon ActionLink to:
else
{
if(!Request.RawUrl.Contains("/Account/LogOn"))
{
Session["WhereWasI"] = Request.Url.AbsoluteUri;
}
%>
[ <%: Html.ActionLink("Log On", "LogOn", "Account") %> ]
<%
}
What we're basically doing to tracking the page the user is on if they aren't logged in. Because the Logon link is also rendered on the logon page itself we need to exclude that, hence the if statement:
if(!Request.RawUrl.Contains("/Account/LogOn"))
Then in your AccountController.cs Logon postback action method you can return the user to where they were on the site but using http insteadof https::
I've also included the redirect to non-SSL should there be a returnUrl supplied by ASP.NET Forms Authentication:
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
if (MembershipService.ValidateUser(model.UserName, model.Password))
{
FormsService.SignIn(model.UserName, model.RememberMe);
if (Url.IsLocalUrl(returnUrl))
{
//
// 1. All content is protected by web forms `<authorization>`:
// If there was a return URL then go back there
//
if(!String.IsNullOrWhiteSpace(returnUrl))
{
return Redirect("http://" + Request.Url.Host + returnUrl);
}
}
else
{
//
// 2. Users have to logon to enable additional features:
//
if (Session["WhereWasI"] != null)
{
return Redirect(
Session["WhereWasI"].ToString().Replace("https", "http"));
}
return RedirectToAction("Index", "Home");
}
}
else
{
ModelState.AddModelError("",
"The user name or password provided is incorrect.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
The example is maybe a bit simplistic but you should be able to get the general idea.

Resources