So I am working on a project with multiple areas and we would like to configure IIS to rewrite our requests to make the urls nicer. I have been messing around with the URL rewrite module all day and I cannot get the desired results.
Example:
I currently have a long url like 'http://register.example.com/Registration/Register/New' where Area = Registration, Controller = Register...
I would like the user to request the site by 'http://register.example.com' and it hits the register controller which I have configured to default to the 'New' action. Because I gave the subdomain of register, IIS knows that it will be using the 'Registration' area.
The finish url would be something like 'http://register.example.com/Register/Finish'
Is this possible?
Thanks,
John
seeing as how you have marked MVC in your tags, you realize you can do this with a route.
''# Default Catch All MapRoute
routes.MapRouteLowercase( _
"Registration", _
"{controller}/{action}/{step}", _
New With {.controller = "Register", .action = "Registration", .step = "New"})
Then you just make a separate "website" in IIS to host the registration application.
PS... IMO sub-domains are overrated and often bad practice for the implementation you are describing. A sub-domain is used to describe a physical computer (IE your SQL server could be on sql.domain your web is on both domain and www.domain, and your email is on smtp.domain), it should not be used to separate sections of a single website. Also, many search engines index http:/subdomain.example.com separate from http://www.example.com, so your SEO values go way way down.
Related
I am about to move a webshop from old webforms to new .Net Core (.Net 5) site.
The old urls have a lot of good rating on google and I would like to be able to make a permanent redirect from an aspx page to .net core page.
Etc.:
www.mydomain.com/products/great-backpack-1234.aspx
to
www.mydomain.com/great-backpack
I believe that requires that I have both .net core and aspx site running on the same domain.
Is this possible?
Or do any one have any other solution ideas?
Best regards
Thats probably not needed to run both on the same domain or space. It seems everything will end in .aspx, and assuming you are using MVC, a controller function to catch-all requests that don't match other routes, then check to see if it ends in aspx, should do it for you. You can put it in an existing controller, but I personally would put it in a new one to separate concerns
public class RedirectController : Controller
{
[Route("{**url}", Order = 999)]
public IActionResult RedirectPage(string url)
{
//Redirect logic based on the URL given, making sure it ends in aspx
}
}
The url would come across in the url parameter as a string and you can check to see if it ends in aspx, and what the page name was to determine where to send them. So "www.mydomain.com/products/great-backpack-1234.aspx" would come across in the url parameter as "products/great-backpack-1234.aspx". Note that the order field in the route attribute assures that it will be the last match checked for patterns, so it shouldn't mess with anything else.
Experience cloud vistor id is used. App, web are using same adobe launch library. When I login into app url change and mid changes and then if I navigate from app to web responsive page mid is changed and I am not seeing any cross-domain pathing report from app to web ?
anything do I need to do with s.cookiedomainperiod or anything to make this work?
The Experience Cloud Visitor ID is not automatically carried over from the native mobile app to a (mobile) web page. The long story short is native apps don't really store data locally in the same way as web browsers, so there's no automatic ability to use the same local storage mechanism/source between the two.
In order to do this, you must add some code to the mobile app to append the mid value to the target URL, e.g. :
Android
String urlString = "http://www.example.com/index.php";
String urlStringWithVisitorData = Visitor.appendToURL(urlString);
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(urlStringWithVisitorData));
startActivity(browserIntent);
iOS
NSURL *url = [NSURL URLWithString:#”http://www.example.com/index.php"];
NSURL *urlWithVisitorData = [ADBMobile visitorAppendToURL:url];
[[UIApplication sharedApplication] openURL:urlWithVisitorData];
If implemented properly, you should now see a adobe_mc= parameter appended to the target URL. Then on page view of the target page, if you have the Adobe Analytics javascript and Experience Cloud Visitor ID libraries implemented, they will automatically look for and use that value instead of generate a new value (should not require any config / coding on this end).
Update:
#Ramaiyavraghvendra you made a comment:
Hi #Crayon, mny thanks for your profound answer. I am sorry that i
missed to inform that this app is not native one but this is a SPA
app. so the implementation of entire app is also done through launch.
Could you pl help in this case then.
I'm not entirely sure I understand your issue. If you are NOT moving from a native mobile app to web page, and your mobile app is really a web based SPA that outputs Launch as regular javascript code throughout the entire app, then you shouldn't have to do anything; the Experience Cloud ID service should carry over the id from page to page.
So it sounds to me like perhaps your Experience Cloud Visitor ID and/or Adobe Analytics collection server settings are not configured correctly. the cookie domain period variables may be an issue, if logging in involves moving from say www.mysite.com to www.mysite.co.uk or similar, but shouldn't be a problem if the TLD has the same # of periods.
Or, the trackingServer and trackingServerSecure variables may not be configured properly. In practice, I usually do not set trackingServerSecure at all. These variables get kind of confusing and IMO buggy in different scenarios vs. what you are using, so I tend to use the "secure" value in the trackingServer field and leave the trackingServerSecure blank, and then Experience Cloud Visitor ID and Adobe Analytics will just use the secure version 100% of the time.
Or..it could be a number of other config variables not properly set. It's hard to say if any of this is off, without access to the app and Launch container.
Also you may want to check the response headers for your logged in pages. It may be that they are configured to reject certain existing non-https cookies or something else that effectively causes the existing cookies to be unreadable and make the Experience Cloud ID service generate a new ID and cookies.
Or.. maybe your app kind of is a native mobile app but using an http wrapper to pull in web pages, so it is basically a web browser but it is effectively like moving from one web browser to another (e.g. starting on www.site.com/pageA on Chrome, and then copy/pasting that URL over to Internet Explorer to view). So effectively, different cookie jar.
Launch (or DTM) + Experience Cloud ID (Javascript methods)
In cases such as the last 2 paragraphs, you have to decorate your target links the same as my original answer, but using the Launch + Experience Cloud ID Service javascript syntax:
_satellite.getVisitorId().appendVisitorIDsTo('[your url here]');
You write some code to get the target URL of the link. Then run it through this code to return the url with the parameters added to them, and then you update your link with the new URL.
Super generic example that just updates all links on the page. In practice, you should only do this for relevant link(s) the visitor is redirected to.
var urls = document.querySelectorAll('a');
for (var i = 0, l = urls.length; i < l; i++) {
if (urls[i].href) {
urls[i].href = _satellite.getVisitorId().appendVisitorIDsTo(urls[i].href);
}
}
In a plain Play application I have the following scenario.
A route file which looks like this:
GET /accounts/add controllers.Accounts.add()
POST /accounts controllers.Accounts.create()
The first route results in a view where I can add a new account. The form to submit the new account looks something like this:
#helper.form(action = routes.Accounts.create()) {...}
Now the controller binds the input to the form and checks for any validation errors:
public static Result create() {
Form<Account> form = Form.form(Account.class).bindFromRequest();
if (form.hasErrors()) {
return badRequest(views.html.account.add.render(form));
}
...
}
Now the thing is, the client will see the same view with some additional error messages. However, meanwhile the URL has changed from http://example.com/accounts/add to http://example.com/accounts.
If the client now reloads the browser this calls GET http://example.com/accounts (which isn't even mapped in this scenario - thus getting a 404 - Not Found).
Maybe it's just me but I find this kind of annoying and browsing some GitHub projects I couldn't find a good solution for this case.
Of cause things would be much simpler if the second route is rewritten to:
POST /accounts/add controllers.Accounts.create()
... in which case everything works fine. But from a REST point of view this doesn't feel good either. The same applies to update scenarios (having GET /accounts/:id/update vs. PUT /accounts/:id).
Is there a guide on how to handle this? Am I getting something wrong or is this no problem at all (from a pragmatic point of view)?
It's not possible to leave the previous URL because a request for a new address has already been made. A controller only provides response for a requested resource. To go to the previous URL you could only make a redirect in case of validation failure but you would lost errors that way so this is not a solution.
I suggest mapping both actions with the same URL. This way you would solve problem with the browser reload.
If you create a REST service for http clients that aren't browsers you will probably want to serve different response than a simple http page. The separation of actions for particular clients could be a good solution for keeping REST API clean and a browser user happy.
Several web application authentication protocols (like WS-Federation and the SAML protocol, i.e., so-called 'passive' protocols, and apparently also ASP.NET Forms authentication, see this StackOverflow question, and AppEngine, see this GWT bug comment) lose the original 'URL fragment', i.e. the part after the #-sign.
What happens is roughly the following: in a clean browser (so no cached info/cookies/login information) I open URL (1) http://example.com/myapp/somepage?some=parameter#somewhere. This makes the browser request (2) http://example.com/myapp/somepage?some=parameter, the server redirects me to my identity provider (including URL (2) in the authentication request), and ultimately I'm redirected back to where I came from, which is URL (2): that is the only URL that the server knows about. But I wanted to go to URL (1), and the URL fragment ('anchor') has been lost along the way, actually in the first step already.
This seems to be a fundamental limitation of these protocols, since the server never sees the URL fragment at all.
I know that it according to specifications that the browser requests (2) from the server, when I navigate to (1), leading to this fragment-losing limitation on the SAML protocol, WS-Federation, etc. My question is: how do I work around this limitation?
The obvious workaround is to avoid URL fragments, as suggested in this answer. However, for our specific web application that is not nice, since we use bookmarkable URL fragments in our single-page GWT application, to make sure that a navigation within our application does not cause the page to reload.
My question: What other workarounds or standard patterns are there for this situation?
(I'm specifically interested in a GWT + SAML protocol solution.)
You basically have two options:
avoid using location.hash (use HTML5's pushState instead, at least on browsers that support it; and/or propose a way to generate permalinks within your app – Google Groups does that)
do the redirection using JavaScript. I.e. instead of sending a redirect from the server, send an empty HTML page with some script that takes the full URL (with the hash) and does the redirection using location.assign() or location.replace(). With a bit of luck (depending on the servers), you'll be redirected to that full URL after authentication.
You can of course do both: if the link is a deep-link into the app, then do the redirect (i.e. assume there's no hash), otherwise send a page with JS to make sure you don't lose any state present in the hash.
And finally the obvious third solution, far from ideal: don't do anything, and try to educate users that when they needed to (re)authenticate then they should re-paste the URL or re-click the link or re-click the bookmark.
According to RFC 1738 anchor tags are not sent by the client to the server, when requesting for a resource.
Anchor tags are used to identify a location within a resource and not a different resource on the server. In order to identify the location in the resource, the client needs to fetch the complete resource from the server, and this process need not involve transfer of information about the fragment (as it does not mean anything to the server).
If you do wish to send the fragment character (#) to the server, then you'll need to encode it in the query string, or the client(browser) will simply ignore that section of the URL when it sends the request to the server.
EDIT:
I don't know any real solution but to work around this issue you need to save your full return URL (with anchor tags) somewhere on the client side, because server don't know anything about anchors. For that you could use SessionStorage (http://www.w3schools.com/html/html5_webstorage.asp) to temporary store ReturnUrl until login process is completed. Please note that it won't be supported on older browsers (like <= IE7).
In that case workaround would look something like this:
<script>
if(typeof(sessionStorage) == 'undefined')
{
sessionStorage = {
getItem: function(){},
setItem: function(){}
};
}
window.onload = function ()
{
var key = 'ReturnUrl';
//try to get last returnUrl with anchors
var returnUrl = sessionStorage.getItem(key);
//if we got something, do the navigation
if(returnUrl !== undefined && returnUrl !== document.URL)
{
//clean it up
sessionStorage.setItem(key, null);
//navigate to last URL
window.location = returnUrl;
}
else
{
//store url
sessionStorage.setItem(key, document.URL);
}
}
</script>
PS. Bear with me if there are some syntax errors because I wrote it down from top of my head and didn't try it.
This is a little different than all the other Rails 3 redirect https questions out there. Let me explain.
In order to publish our site with Phusion Passenger we had to create a subdomain and use a symlink (or softlink or alias) from the www/rails folder to /home/user/app/railsapp.
In order for the HTTPS to work (because of various domains issues) we need to have a rewrite mod that actually creates this route:
https://my.site.com/rails
Notice the trailing /rails route.
This route does not exist on our app. So what I need is a way to redirect anything that comes in with that route to:
https://my.site.com/login
So I thought I'd do this, in the routes.rb file have this:
match '/rails' => 'sessions#redirect_to_login'
In sessions_controllers.rb:
def redirect_to_login
redirect_to login_path, :status => :moved_permanently
end
This results in the app complaining that it can't find /rais/login/ so it's still seeking that /rails bit.
If I add something like redirect_to "/" which in turn will send you to my.site.com/login with a redirect when you're not logged in, I'll get an error of too many redirects in the browser.
redirect_to login_url didn't do the trick either.
It gets a bit more complicated in the sense that whenever I'm using the https protocol for that site, it will append that /rails route so I need a way to remove it from all the links. For example, https://my.site.com/movies will get translated to https://my.site.com/rails/movies.
Either remove the /rails or redirect all https traffic to http except for the login page.
I'm sure there is a relatively easy fix for this, but I can't figure it out.
Help is appreciated.