Running both aspx and .Net Core (.Net 5) webpages on same server and domain - redirect

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.

Related

Play Framework: Don't change URL after form validation failed

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.

URL fragment lost as part of SAML token authentication; workaround / standard pattern?

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.

Use RESTful URLs in a non-MVC site

I started the site using AST.NET Razor template, not ASP.NET MVC template.
I recall seeing somewhere on the Internet that even without MVC, it's possible to use RESTFul URLs in the razor-based ASP.NET site. It appears to work without the CHTML extension names right out of the box -- www.test.com/car automatically redirects to www.test.com/car.cshtml.
But, what if I used www.test.com/car/2, how would I get to the "2" inside the View without using MVC? I really hope that's something already baked in.
Found it -- it's in UrlData
http://beta.asp.net/web-pages/tutorials/aspnet-razor-pages/18-customizing-site-wide-behavior
section "How Routing Works"
Look at the WebGet Attribute. It has a UriTemplate.
Example:
WebGet(UriTempate="{Id}")<br>
public JsonResult Get(int Id)
{
}

IIS7 URL rewrite + subdomain + ASP.Net MVC2

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.

How to RESTful delete record Asp.Net Mvc 2

I have delete links in my Asp.Net Mvc2 application.
/{controller}/Delete/{id}
It seems using link to delete has a security risk. Don’t use Delete Links because they create Security Holes
I found this Implementing RESTful Routes & Controllers in ASP.NET MVC 2.0 but I am not sure how to implement a simple delete functionality using the new HttpDeleteAttribute class.
Are there any examples on deleting, the RESTful approach?
The RESTful approach to a Delete is to send enough information to identify the resource and use the HTTP command DELETE (or some alternative for web pages). But all of that is detailed in the article, so I don't think that's what you're really asking.
If you mean "What do I do instead of a Delete link?", the answer is usually to go to a "Are you sure you want to delete Product 8496?" form where the button's action POSTs the delete request. That form can either be on a new page or a modal popup, or both if you want to combine usability and accessibility.
It's a (more of) a security risk if you dont use the [HttpPost] attribute on the controller.
Besides that, your approach isn't a restful one.
The idea is that you have just one Url that can be passed different Http Verbs which are implicit
Return all: /Product/ [HttpGet]
Return One: /Product/43 [HttpGet]
Add : /Product/ (Product info in form post) [HttpPut] or [HttpPost]
Delete: /Product/43 [HttpDelete]
You can do this using MVC in the standard form or JQuery
And to answer the question:
Add a delete link like this Delete Product but hook into it using the JQuery live events so that it hijacks the click using .preventDefault, then call the url as an ajax request with a DELETE verb.
Need more help let me know