stripping default.aspx and //www from the url - c#

the code to strip /Default.aspx and //www is not working (as expected):
protected void Application_BeginRequest(object sender, EventArgs e)
{
HttpContext context = HttpContext.Current;
string url = context.Request.RawUrl.ToString();
bool doRedirect = false;
// remove > default.aspx
if (url.EndsWith("/default.aspx", StringComparison.OrdinalIgnoreCase))
{
url = url.Substring(0, url.Length - 12);
doRedirect = true;
}
// remove > www
if (url.Contains("//www"))
{
url = url.Replace("//www", "//");
doRedirect = true;
}
// redirect if necessary
if (doRedirect)
{
context.Response.Redirect(url);
}
}
it works usually, but when submitting a form (sign in for example) the code above INTERCEPTS the request and then does a redirect to the same page. example:
try to arrive at page: ~/SignIn/Default.aspx
the requests gets intercepted and fixed to: ~/SignIn/
fill the form, click sign in
the current page url goes from: ~/SignIn/ to ~/SignIn/Default.aspx and gets fixed again, thus voiding the processing of the method SignIn (which would have redirected the browser to /SignIn/Success/) and the page is reloaded as ~/SignIn/ and no sign in was done.
please help. not sure what / how to fix here.
the main REQUIREMENT here is:
remove /Default.aspx and //www from url's
thnx

Your problem here is to do with GET and POST requests. When you call Response.Redirect, you instruct the client to make a new GET request to the URL you provide. So if you call this early in a request like a form postback that was actually a POST request, you lose the post. Since most POSTs should themselves redirect once the action is complete, it may be enough to just only apply the logic you have above to a GET request.
You can access the request method (GET or POST) using Request.HttpMethod.

Related

Authorize.net Accept Hosted Customer Profile Page has no button to return

I am using the Authorize.net Accept Hosted "Get Hosted Profile Page" action using redirect instead of iframe. Everything is working so far, redirect is happening, token is getting passed . . . but there is literally no button to proceed and/or go back to my site after the customer is redirected to this page (?). Am I missing something? I am passing a redirect URL in to get my token, so I'd expect there to be something happening.
I'm using the .NET SDK on my backend.
string token = null;
var settings = new settingType[]
{
new settingType
{
settingName = settingNameEnum.hostedProfileReturnUrl.ToString(),
settingValue = model.ReturnUrl.AbsoluteUri
// ^^^ here's why my redirect url goes
}
};
var profileReq = new getHostedProfilePageRequest();
profileReq.customerProfileId = model.CustomerProfileId;
profileReq.hostedProfileSettings = settings;
var controller = new getHostedProfilePageController(profileReq);
controller.Execute();
var resp = controller.GetApiResponse();
// ^^^ this all works fine, token is returned
Here's the page to which I'm redirected at https://test.authorize.net/customer/manage (the sandbox), below. There's no button to advance or go backwards. I've tried clicking everywhere.
How do I get back to my site?

Custom authorize attribute doesn't work after deploying to IIS

I have overridden the HandleUnauthorizedRequest method in my asp.net mvc application to ensure it sends a 401 response to unauthorized ajax calls instead of redirecting to login page. This works perfectly fine when I run it locally, but my overridden method doesn't get called once I deploy to IIS. The debug point doesn't hit my method at all and straight away gets redirected to the login page.
This is my code:
public class AjaxAuthorizeAttribute : AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
filterContext.HttpContext.Response.Clear();
filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
filterContext.Result = new JsonResult
{
Data = new
{
success = false,
resultMessage = "Errors"
},
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
filterContext.HttpContext.Response.End();
base.HandleUnauthorizedRequest(filterContext);
}
else
{
var url = HttpContext.Current.Request.Url.AbsoluteUri;
url = HttpUtility.UrlEncode(url);
filterContext.Result = new RedirectResult(ConfigurationManager.AppSettings["LoginUrl"] + "?ReturnUrl=" + url);
}
}
}
and I have the attribute [AjaxAuthorize] declared on top of my controller. What could be different once it's deployed to IIS?
Update:
Here's how I'm testing, it's very simple, doesn't even matter whether it's an ajax request or a simple page refresh after the login session has expired -
I deploy the site onto my local IIS
Login to the website, go to the home page - "/Home"
Right click on the "Logout" link, "Open in a new tab" - This ensures that the home page is still open on the current tab while
the session is logged out.
Refresh Home page. Now here, the debug point should hit my overridden HandleUnauthorizedRequest method and go through the
if/else condition and then redirect me to login page. But it
doesn't! it just simply redirects to login page straight away. I'm
thinking it's not even considering my custom authorize attribute.
When I run the site from visual studio however, everything works fine, the control enters the debug point in my overridden method and goes through the if/else condition.
When you deploy your web site to IIS, it will run under IIS integrated mode by default. This is usually the best option. But it also means that the HTTP request/response model isn't completely initialized during the authorization check. I suspect this is causing IsAjaxRequest() to always return false when your application is hosted on IIS.
Also, the default HandleUnauthorizedRequest implementation looks like this:
protected virtual void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
// Returns HTTP 401 - see comment in HttpUnauthorizedResult.cs.
filterContext.Result = new HttpUnauthorizedResult();
}
Effectively, by calling base.HandleUnauthorizedRequest(context) you are overwriting the JsonResult instance that you are setting with the default HttpUnauthorizedResult instance.
There is a reason why these are called filters. They are meant for filtering requests that go into a piece of logic, not for actually executing that piece of logic. The handler (ActionResult derived class) is supposed to do the work.
To accomplish this, you need to build a separate handler so the logic that the filter executes waits until after HttpContext is fully initialized.
public class AjaxAuthorizeAttribute : AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
filterContext.Result = new AjaxHandler();
}
}
public class AjaxHandler : JsonResult
{
public override void ExecuteResult(ControllerContext context)
{
var httpContext = context.HttpContext;
var request = httpContext.Request;
var response = httpContext.Response;
if (request.IsAjaxRequest())
{
response.StatusCode = (int)HttpStatusCode.Unauthorized;
this.Data = new
{
success = false,
resultMessage = "Errors"
};
this.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
base.ExecuteResult(context);
}
else
{
var url = request.Url.AbsoluteUri;
url = HttpUtility.UrlEncode(url);
url = ConfigurationManager.AppSettings["LoginUrl"] + "?ReturnUrl=" + url;
var redirectResult = new RedirectResult(url);
redirectResult.ExecuteResult(context);
}
}
}
NOTE: The above code is untested. But this should get you moving in the right direction.

"An item with the same key has already been added." while adding "/&output=embed"

Implementing a MVC application in C# with Evernote API. I am using the AsyncOAuth.Evernote.Simple nuget package. Receiving and error of Refused to display in a frame because it set 'X-Frame-Options' to 'SAMEORIGIN', when trying to navigate to URL that fires off the OAuth process.
There is an iframe that is surrounding my code (which can not be altered). After implementing the code an error is generated: "An item with the same key has already been added". This error occurs when requestToken is hit for the first time.
Below is my EvernoteProviderController.cs
public class EvernoteProviderController : Controller
{
// Initialize Oauth call, pulling values from web.config
EvernoteAuthorizer EvernoteAuthorizer = new EvernoteAuthorizer(ConfigurationManager.AppSettings["Evernote.Url"] + "&output=embed", ConfigurationManager.AppSettings["Evernote.Key"], ConfigurationManager.AppSettings["Evernote.Secret"]);
// This method makes the original call to Evernote to get a token so that the user can validate that they want to access this site.
public ActionResult Authorize(bool reauth = false)
{
// Allow for reauth
if (reauth)
SessionHelper.Clear();
// First of all, check to see if the user is already registered, in which case tell them that
if (SessionHelper.EvernoteCredentials != null)
return Redirect(Url.Action("AlreadyAuthorized"));
// Evernote will redirect the user to this URL once they have authorized your application
var callBackUrl = Request.Url.GetLeftPart(UriPartial.Authority) + Url.Action("ObtainTokenCredentials");
// Generate a request token - this needs to be persisted till the callback
var requestToken = EvernoteAuthorizer.GetRequestToken(callBackUrl);
// Persist the token
SessionHelper.RequestToken = requestToken;
// Redirect the user to Evernote so they can authorize the app
var callForwardUrl = EvernoteAuthorizer.BuildAuthorizeUrl(requestToken);
return Redirect(callForwardUrl);
}
// This action is the callback that Evernote will redirect to after the call to Authorize above
public ActionResult ObtainTokenCredentials(string oauth_verifier)
{
// Use the verifier to get all the user details we need and store them in EvernoteCredentials
var credentials = EvernoteAuthorizer.ParseAccessToken(oauth_verifier, SessionHelper.RequestToken);
if (credentials != null)
{
SessionHelper.EvernoteCredentials = credentials;
return Redirect(Url.Action("Authorized"));
}
else
{
return Redirect(Url.Action("Unauthorized"));
}
}
// Show the user if they are authorized
public ActionResult Authorized()
{
return View(SessionHelper.EvernoteCredentials);
}
public ActionResult Unauthorized()
{
return View();
}
//Redirects user if already authorized, then dump out the EvernoteCredentials object
public ActionResult AlreadyAuthorized()
{
return View(SessionHelper.EvernoteCredentials);
}
public ActionResult Settings()
{
return View();
}
}
Has anyone had this issue with iframes before or knows in what direction I should go? I am trying to embed my URL endpoint so I can get around the iframe error.
Solved the error.
A bit of back story:
The purpose of this application was to provide the OAuth page where a user can sign up which will generate a AuthToken and NotebookURL, (both are needed with Evernote API to pull read/write Notes - which is Evernote's object).
The previous behavior (before I changed it), was when a user clicked on the link - they will be redirected (in the same window) to the Evernote OAuth page.
This caused issues for me, because I had another wrapper around my code (iframe). So in non-technical terms, I had a iframe within an iframe within an iframe.
Workaround
Created a JavaScript code which would add an click event listener, which would then create a popup using window.open.
$("#btnStart").click(function () {
myWindow = window.open(baseUrl + "/EvernoteProvider/Authorize", '_blank', 'width=500,height=500, scrollbars=no,resizable=no');
myWindow.focus();
});

When is Application_BeginRequest invoked in parent site

I have this senario where my site www.skinb5.com should redirect to www.skinb5.com/au/
and www.skinb5.com/au should directly go to the www.skinb5.com/au and www.skinb5.com/us
should go to www.skinb5.com/us.
www.skinb5.com is a parent site which pretty much does nothin but to redirect. /au/ and /us/ are child sites sitting under it.
Please have a look at my Global.asax file in my parent site where the only redirect happens.
The problem is when i go www.skinb5.com/us/ it returns 200 which is good. But
www.skinb5.com/au/ it returns 302 to www.skinb5.com/au/. Though it doesn't go in an infinite loop, I am concerned why it returns 302.
you might want to test here at http://www.internetofficer.com/seo-tool/redirect-check/
My questions is, when I invoke www.skinb5.com/au/ directly, will the application_beginRequest in parentsite be invoked? Shouldn't it directly go to the child site? If so how does the 302 redirect happen.
protected void Application_BeginRequest(object sender, EventArgs e)
{
var redirectSite = "au";
HttpCookie languageCookie = HttpContext.Current.Request.Cookies.Get("Customer.SelectLanguageID");
if (languageCookie != null)
{
redirectSite = languageCookie.Value.Split('-')[1];
}
string rawUrl = HttpContext.Current.Request.RawUrl;
if (string.IsNullOrEmpty(rawUrl))
{
rawUrl = "/";
}
rawUrl = redirectSite + rawUrl;
bool useSsl = IsCurrentConnectionSecured();
var storeHost = GetStoreHost(useSsl);
if (storeHost.EndsWith("/"))
storeHost = storeHost.Substring(0, storeHost.Length - 1);
string url = storeHost + '/' + rawUrl;
url = url.ToLowerInvariant();
HttpContext.Current.Response.Redirect(url, true);
HttpContext.Current.Response.End();
}
A redirect tells the browser to load a different URL. The browser does this just as though the new URL was typed in the address bar. It is a request like any other.
So all requests and redirects will cause Application_BeginRequest() to fire.
If you don't want it to do anything on the redirected request, you'll need to test the target URL and decide if any action is to be taken.

Custom authorize attribute only works on localhost

I have a custom authorize attribute used for Ajax requests:
public class AjaxAuthorize : AuthorizeAttribute {
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) {
UrlHelper urlHelper;
if (filterContext.HttpContext.Request.IsAjaxRequest()) {
urlHelper = new UrlHelper(filterContext.RequestContext);
filterContext.HttpContext.Response.StatusCode = 401;
//Return JSON which tells the client where the login page exists if the user wants to authenticate.
filterContext.HttpContext.Response.Write(new JavaScriptSerializer().Serialize(
new {
LoginUrl = string.Format("{0}?ReturnURL={1}", FormsAuthentication.LoginUrl, urlHelper.Encode(filterContext.HttpContext.Request.Url.PathAndQuery))
}
));
filterContext.HttpContext.Response.End();
} else {
base.HandleUnauthorizedRequest(filterContext);
}
}
}
When I run the application locally I get the JSON result back from the Ajax request. However, when I put the code on my beta server I end up getting the IIS 401 HTML response.
Does anyone see something wrong with my code that would make this work only on localhost? Additionally, if anyone has a better idea for returning the JSON result I am open to that as well.
There is some strange power of StackOverflow that results in the OP thinking through the question differently after posting. I'll leave my answer here in hopes that it might benefit someone else.
It just occurred to me that IIS7 was getting in the way. I fixed this by adding one line of code:
filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;

Categories