I am building an application that is an ASP.NET MVC and Angular 1.x hybrid. I use MVC as a shell and then layered Angular on top of it. I did this for a couple of reasons. First, it provided me with the ability to create an HTML helper class for script references to support cache busting. Second, it allows me to "push" a set of server side configurations to angular for things like web service URLs, etc. All of this seems to be working ok except for a single issue.
Currently, I am having to process a couple of IIS rewrite rules to make all of this work properly. In testing in a staged environment today, I published a link to Facebook that does not appear to work properly though and I'm not really sure why. Based on my understanding of the rule syntax, I thought it would work, but isn't.
Here are the IIS rewrite rules I currently have in web.config and why I have each rule:
<system.webServer>
<rewrite xdt:Transform="Replace">
<rules>
<rule name="cachebust">
<match url="([\S]+)(/v-[0-9]+/)([\S]+)" />
<action type="Rewrite" url="{R:1}/{R:3}" />
</rule>
<rule name="baseindex" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
<rule name="non-www" stopProcessing="true">
<match url="(.*)" negate="false"></match>
<conditions>
<add input="{HTTP_HOST}" pattern="^exampledomain\.org$" negate="true"></add>
</conditions>
<action type="Redirect" url="http://exampledomain.org/{R:1}"></action>
</rule>
</rules>
</rewrite>
</system.webServer>
1) The "cachebust" rule is used for script cache busting. The HTML helper I wrote takes the path of the script file and inserts a fake version # into the path. For example, "scripts/example.js" would become "scripts/v-123456789/example.js", where "123456789" are the ticks from the current date and time. This rule will rewrite the URL back to the original but since the page is output with the version stamped path, it will force my angular scripts to be reloaded by the browser in the event that they change. This rule appears to be working fine. Credit to Mads for this: https://madskristensen.net/blog/cache-busting-in-aspnet/
2) The "baseindex" rule is used to rewrite the URL so that ASP.NET will always serve the index.cshtml page that is used as the root for my site. This rule also appears to work fine. Credit to this SO QA: How do I configure IIS for URL Rewriting an AngularJS application in HTML5 mode?
3) The "non-www" rule is the problematic one. The goal of the rule is to redirect all www requests to non-www requests based on ScottGu's blog post (link below) about canonical host names and how they affect SEO. This rule works perfectly fine for www.example.org as it redirects the URL to example.org, but it fails when the URL looks like this: www.example.org/entity/1 where entity is a detail page for id = 1. In practice, it fails for www.example.org/about too.
Since my web services require CORS to be enabled as they are on separate domains, this also needs to happen for that.
https://weblogs.asp.net/scottgu/tip-trick-fix-common-seo-problems-using-the-url-rewrite-extension
For sake of completeness: HTML 5 mode is enabled for Angular and my route to the specified page is defined as such:
.state('entityDetail', {
url: '/entity/{id}',
templateUrl: 'app/pages/entity/entityDetail.html',
controller: 'entityDetailController',
controllerAs: 'entityDetailCtrl'
})
Also, my _Layout.cshtml contains the base href of:
<base href="/" />
and script references like such (except for the angular scripts that require the cachebust rule listed above):
<script type="text/javascript" src="scripts/jquery-2.2.0.min.js"></script>
I've tried several different versions of the rule, but they all lead to different issues. Since there are so many different things at play here, I am concerned that I am overlooking something or that I am wrong in my thinking on how this "should" work.
Any help would be greatly appreciated.
It took some trial and error to figure this all out, but wanted to post the answer I finally came up with in the event that someone else ever tries to marry ASP.NET MVC and Angular 1.x together while allowing cache busting in Google Chrome.
It turned out to be a couple of things:
1) The order of the rules.
2) The stopProcessing flag and when it should be enabled.
In summary, to get this to work, I built the rules so that all requests must be redirected to www.exampledomain.com and then stop processing rules until the reprocessed request happens (this time www. will be guaranteed). Then, the cachebust rule must happen BEFORE the rewrite to the base index of "/", otherwise, the entire HTML document is returned by the server when each of the script files that must be "busted" load. This was really the majority of my issue from the very beginning. The whole process was honestly a little confusing so if this answer is not sufficient, please comment and I will try my best to better articulate the "whys" I found in my research. Hope this helps someone else though...it only took 10 days to figure out. :)
<system.webServer>
<rewrite xdt:Transform="Replace">
<rules>
<rule name="forcewww" patternSyntax="ECMAScript" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAny">
<add input="{HTTP_HOST}" pattern="^exampledomain.com$" />
</conditions>
<action type="Redirect" url="http://www.exampledomain.com/{R:0}" />
</rule>
<rule name="cachebust">
<match url="([\S]+)(/v-[0-9]+/)([\S]+)" />
<action type="Rewrite" url="{R:1}/{R:3}" />
</rule>
<rule name="baseindex">
<match url=".*" />
<conditions logicalGrouping="MatchAll">
<add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
<add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
</conditions>
<action type="Rewrite" url="/" />
</rule>
</rules>
</rewrite>
</system.webServer>
Instead of writing redirect rules in an app.config file, you can use the following in your Program.cs file:
var builder = WebApplication.CreateBuilder(args); // Followed by service configurations...
var app = builder.Build(); // followed by app configurations...
// The following will fix your redirect woes:
app.UseStaticFiles();
app.MapFallbackToFile("index.html");
Related
I moved my project to a new server (from abc.com/eco to abc2.com/eco) and created a HTTP redirect rule to redirect every abc.com/eco requests to abc2.com/eco. which works fine on abc.com/eco requests.
The problem is, Urls after eco does not get redirected.
For example:
abc.com/eco/departments/main.aspx?id=123
does not redirect to
abc2.com/eco/departments/main.aspx?id=123
The following Url rewrite rule doesnt work also:
<rule name="Redirects to abc2.com" patternSyntax="ECMAScript" stopProcessing="true">
<match url=".*" />
<conditions logicalGrouping="MatchAny">
<add input="{HTTP_HOST}" pattern="^abc.*(com|net)$" />
</conditions>
<action type="Redirect" url="http://abc2.com/{R:0}" />
</rule>
I looked over tens of questions but all are asking about the subdirectory replace.
Similar questions but not answering mine:
Question 1
Question 2
The rule is working properly on my side.
Have you cleaned cache before testing a new rewrite rule with long term permanent redirect.
If you didn't clean the browser cache, your previous HTTP redirection will keep redirecting your URL to http://abc2/eco
I am using angular 5 inside MVC 5 using and I am using angular routing inside this. Everything working fine but when there is an angular route URL on the browser address bar and I am doing F5 it's giving the error- The resource cannot be found.
I am sure its because this URL pattern does not match with my MVC routing but it matches with angular routes.
How to solve this?
It is simple to solve this problem. Do this in your imports modules:
RouterModule.forRoot(routes, { useHash: true }).
In this case, the Url after the hash is not sended anymore to your server side.
For more information go here.
Odds are you need to have the UrlRewriter module installed for IIS and then you need to have the following in your web.config at system.webServer/rewrite/rules
<rule name="Angular 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="^/(api)" negate="true" />
</conditions>
<action type="Rewrite" url="/Home/Index?url={UrlEncode:{R:0}}" />
</rule>
The specifics of the rewrite rule though will depend on your app. I'm hooking up my angular root html node in my Home/Index view. If you are doing that differently, you will have to update it to route to where you are expecting it to go.
Angular docs
I’ve wanted to use subdomains for sub-sites within a single application for a while now. Basically, instead of setting up multiple sub-sites like this…
http://example.com/shop1.aspx?name=john/
…I wanted this…
http://john.example.com/
I want dynamic subdomain virtually using URL rewrite
I have no idea how to do this.
-----------UPDATE------
After searching over the internet I got following code.it redirect perfect but not rewriting the URL
my page is- http://domain/mySpace.aspx?una=sunil
<rule name="Redirect to Subdomains" stopProcessing="true">
<match url="^mySpace.aspx$" />
<conditions>
<add input="{QUERY_STRING}" pattern="^una=(.+)$" />
</conditions>
<action type="Rewrite" url="http://{C:1}.{HTTP_HOST}"
appendQueryString="false" />
</rule>
But still not able to resolve it.
I have a website hosted in Azure, which will be accessed with the URL https://abc.cloudapp.net/controller1/action1/parameter1
My Customer wants the following.
When we try to access the url "https://abc.cloudapp.net", it should automatically redirect me to the actual url mentioned above for the website.
I want this to be achieved using the web.config. and I tried several combinations (Couple of those are listed below).
Combination 1:
<system.webServer>
<rewrite>
<rules>
<rule name="Redirect to Full URL" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{URL}" pattern="^abc.cloudapp.net$" />
</conditions>
<action type="Redirect" url="https://abc.cloudapp.net/controller1/action1/parameter1" redirectType="Permanent" />
</rule>
</rules>
</rewrite>
</system.webServer>
Combination 2:
<system.webServer>
<rewrite>
<rules>
<rule name="Redirect to Full URL" stopProcessing="true">
<match url="https://abc.cloudapp.net" />
<action type="Redirect" url="https://abc.cloudapp.net/controller1/action1/parameter1" redirectType="Permanent" />
</rule>
</rules>
</rewrite>
</system.webServer>
None of these combinations have worked.
I had posted a workaround below for this problem.
However, I need some quick help in this for a permanent solution.
I still need help on this, can some one help please.
I had found a workaround for this.
When we use the url "https://abc.cloudapp.net", using the default route config we can set this to go to action1 in controller1.
Then in "action1" of "controller1" if we see that the "parameter1" is null (must be delared as a nullable type), we need to initialize the parameter1 to a known value and redirect to the same "action1" in "controller1"
public ActionResult Index(int? parameter1)
{
if(string.IsNullOrEmpty(parameter1)
return RedirectToAction("action1", "controller1", new {#parameter1 = "knownValue"});
else
{
//whatever action you wanted to do based on value in parameter1
}
}
However this whole method calls for hard coding, We are assigning a know value to the paramter1. If there is a change in this value, we need to change the code
Hence I do not recommend this. However for now I have used this workaround. I still need a proper solution around this problem.
MY R & D Continues... ... ... ... ...
I want to Re-write my URL without leaving the current.
I find large number of post related to URL Re-writing, but i did'n get success.
I want if user enter this URL -
http://localhost:16185/Company/CareerWebsite.aspx?org_name=hire-people
URL automatically convert into this format -
http://localhost:16185/hire-people
but the original page (Company/CareerWebsite.aspx?org_name=hire-people) does not leave.
Means, user did't see the original URL(Company/CareerWebsite.aspx?org_name=hire-people) in browser. User can only see virtual URL like /hire-people.
Thanks for help...!!!
Well, if you want to do it directly same way as you described you need to do Redirect 301 or 302. For url-rewriting you'l probably need to install urlRewrite module for iis.
So far you'l need some kind of following url-rewrite rule in web.config file:
<rule name="RedirectUserFriendlyURL1" stopProcessing="true">
<match url="^Company/CareerWebsite\.aspx$" />
<conditions>
<add input="{QUERY_STRING}" pattern="^org_name=([^=&]+)$" />
</conditions>
<action type="Redirect" url="{C:1}" appendQueryString="false" />
</rule>