Pulling external website URL parameters - c#

Currently I have a MVC Registration page which is implemented in an external website.
My question is I need to now extract the previous website's querystring for a certain parameter and read it into my page to register a user into the designated group.
So the workflow looks as follows :
User hits the external website (example: www.test1.com/default.aspx?Code=123asd) with a code in the querystring
user selects Register Now and gets directed to my page.
How will I be able to read the previous querystring code into my MVC page? I do not have access to that website.
EDIT
I currently have a foreach statement which reads the current querystring but this is not pulling the previous request's querystring:
private static string getCode()
{
string nothing = null;
string[] queryStringParaArray = HttpContext.Current.Request.UrlReferrer.Query.Substring(1).Split('=');
if (queryStringParaArray.Length > 0)
{
foreach (var para in queryStringParaArray)
{
if (para.Contains("Code"))
return queryStringParaArray[2];
}
}
return nothing;
}

Have you tried HttpRequest.UrlReferrer property which contains URL of the client's previous request that linked to the current URL. This returns a Uri object and thus you can access the Query property to get the query string value of it.
HttpContext.Request.UrlReferrer
**SideNote: As already commented, there is no guarantee that the referred URL would be present and thus it could be null as well. So would suggest you to pass that query string information directly to your MVC controller while clicking on Register button.

Related

c# mvc: RedirectToAction() and browser navigation buttons

In my application, i am storing an object into session which is passed to a web service to return data to display in a table. If the session exists, then it will not ask the user to input fresh data. However, if a user selects a link called "New List", then the session data will be cleared and the user prompted to enter new data.
In my code, i have an anchor defined like so:
New List
Which will trigger this Controller Action:
public ActionResult NewList()
{
Session["new_list"] = "y";
return RedirectToAction("List");
}
And then continue to execute this action:
public ActionResult List()
{
if ((string)Session["new_list"] == "y")
{
//clear session variables, load fresh data from API
}else{
//display blank table. Ask user to input data to retrieve a list
}
....
}
Now, the issue i have is when a user navigates away from the list page, and then navigates back with the browser's back button, it is still calling newlist. In the history of the browser, instead of storing List it is storing newlist which is causing the session variable to clear. What can i do to stop this from happening or is there a different mechanism to use in c# mvc that can help me achieve the desired effect.
Your main problem here is that the NewList action uses GET when it should really be a POST.
A GET request is never supposed to alter the state of a resource, but simply return the current state of the resource; while a POST request allows for the altering of a resource.
Because you allow the NewList action to be called with a GET request, the user's browser assumes (quite rightly on its part) that nothing bad/undesired will happen if it simply repeats the request in the future, e.g. when a user uses the back button.
If instead a POST request is issued, a user browser will never re-issue the request without the user confirming they actually intended to re-issue it.
The solution to your problem then is modify this to the standard PRG pattern: POST/Redirect/GET; that is, send a POST request to perform the state change, redirect the user browser to another page, and GET the result page. In this scheme, pressing the back-button would effectively "skip" over the state change action and go the previous page the user was on.
To accomplish this in MVC:
[HttpPost]
public ActionResult NewList()
{
//clear session variables, load fresh data from API
return RedirectToAction("List");
}
public ActionResult List()
{
// whatever needs to happen to display the state
}
This does mean that you can't provide the "New List" action directly as a hyperlink in the page, as these will always issue GET requests. You will need to use a minimal form like so: <form method="post" action="#Url.Action("NewList", "Alert")"><button type="submit">New List</button></form>. You can style the button to look like a normal hyperlink as desired.
The reason it storing NewList is because you are redirecting to "Alert/NewList", and its the string in your URL for making hit to "NewList" Action, So whenever you are try back button the browser gets this "Alert/NewList" URL, hence its making hit to action "NewList".
But now, I am not getting why the session gets clear. because you are initializing the session in "NewList" itself. Still i suggest you to use local-storage to assign values with session.

ASP.Net MVC Preventing direct access to action out of RedirectToAction method

My site aims to upload files to sharepoint folders. Users are coming from another system by using a button referencing my site and contains userId and other parameters. When a call comes to my site shown below
http://myapplication/Upload/ToFolder?entityName=new_policy&entityGuid=4451E282-80B0-E611-80E8-C4346BACFC18&systemUserId=1ADEC6E1-008C-430D-A163-D7BA7AD75689
I authenticate user with userId and redirect user to http://myapplication/Policy using RedirectToAction method and setting some parameters to static properties. Because of static properties I use my params but I dont want to do this way. I want to detect that when users types directly http://myapplication/Policy link and throw an error like "You should come from this site only via link on other system."
How can I detect this behaviour of users ?
You could set a tempdata value in the first action...
TempData["isRedirect"] = true;
which gets read by the second action
if(TempData["isRedirect"] == null)
{
//Deny access
}
//Set temp data again so that user can refresh
TempData["isRedirect"] = true;

ASP.NET MVC can I add Request filter to track previous page?

I have ASP.NET MVC Project and I have some pages (let's call it Destination Page) that I can access from multiple pages. So I want to track which page redirects to Destination Page so I can return to it again.
I red about Request Filters .. Can I use it in my case?
Thanks in advance :)
Just pass a return URL in the query string. In other words instead of redirecting like:
return RedirectToAction("Destination");
Do:
return RedirectToAction("Destination", new { returnUrl = Request.RawUrl });
Of course, your "Destination" action needs to accept this as a param:
public ActionResult Destination(Foo otherParam, string returnUrl)
Then, when you're done with whatever you're doing in "Destination", redirect back via:
if (!String.IsNullOrWhiteSpace(returnUrl) && Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
return RedirectToAction("Fallback");
The IsLocalUrl check is to prevent query string tampering, by ensuring that the return URL is actually local (i.e. relative) to your site.
You can get the refering page using Request.UrlReferrer
otherwise save the last url in a session-variable
like
Session["returnUrl"] = Request.RawUrl;
URL Referrer is only populated by an actual client-click (anchor tag, button).
Not when you manually put it in the URL (which is what my JavaScript is doing).
The solution i am doing to have to with is to create a cookie on the whatever.aspx page, and read that cookie from the JavaScript before i redirect again.

Keeping list of attached files of a page with TempData without any conflict with another instanse of the page

Hello Friends...
I have a mvc project and a form with a attachment box (such as yahoo mail compose)
for example "create_request.cshtml"
I want:
each user fill the fields and upload his/her files (i post each file by Ajax when the user select any one) and after submit the form, if the page has error (checked server side), user see the uploaded files in the response page (response form with highlighted errors)...
I implemented the above scenario very nice:
(Ajax+ Tempdata+ save the files server side befor submit + Thumbs of uploaded files befor submit the form)
in my controller:
public void KeepTempData(string name, string value)
{
TempData[name] = value;
}
in my view i send each file name to the server after i upload it by another ajax codes:
ajaxPostData(KeepTempData, "Attachments", $('#Attachments').val());
But i have a problem:
Because i used TempData for keeping list of uploaded filenames, if the user attach a file in the current page then opens a new Tab in her/his browser and goes to the "create_request" page address. He/She see an empty form with a attached file...
My Solution:
Maybe I can solve this problem with a unique key for each page (each form) and keeping it in a session variable and a hidden field for each page request>> using: "Anti Forgery Token with a Salt" or "DateTime.Now"
I found This post on the web. its problem is like as my problem. and its solution is like as my solution.
What is appropriate solutions in MVC for this problem???
What is your recommendation for using TempData's (or Session's) without any conflict when user have different requests of a pages in some tabs of a browser (like firfox)???
TempData has very short lifespan. You should use Session instead of TempData.
Infact session object is the backing storage behind TempData. But the data stored in TempData is available to the current request and Subsequent request.
I Solved this problem by:
Get a key from querystring
If the key is empty
I generate a new and unique key in the action of controller
Redirect the page to a new url with the key (as a querystring key-value)
Else
Adding the key to the ViewBag (for set a hidden field in view)
Save the key in a session variable.
.
public virtual ActionResult Create(string attkey)
{
if (string.IsNullOrEmpty(attkey))
{
attkey = generatNewNameForSession('key'); // for examle: kye_jhtyujbvkjadsgfvn
Response.Redirect("myControle/Create, attkey="+attkey), true);
}
ViewBag.AttachmentsKey = attkey;
if (Session[attkey] == null)
KeepData(attkey, "");
.
.
.
Now each instance of my page has a Identification and now i can decide shown or not shown the previously attached files.

How to pass query string parameter in asp.net?

I am using Access Control service (ACS). I fetched all identity providers (ip) which i set for my application using the following code :
public ActionResult IdentityProviders(string serviceNamespace, string appId)
{
string idpsJsonEndpoint = string.Format(Global.IdentityProviderJsonEndpoint, serviceNamespace, appId);
var client = new WebClient();
var data = client.DownloadData(idpsJsonEndpoint);
return Content(Encoding.UTF8.GetString(data), "application/json");
}
When user click over the signin link the above code called using ajax and get the ips and display them in jquery-ui dialog. And when user click any one of the ips for login the browser redirect to the selected ip login page. After successful login the control return to my control which i set as a returnUrl. Upto this every thing is works fine.
Now what i am trying to do is to pass some values to identity provider (ip) login page and want to get back those values at my returnUrl controller. For this i searched and came to know that there is a query string parameter known as wctx which we can set and get the value at return url. But i dont know how to do this. Can anybody please guid me how can i achieve this?
It is relatively (pretty) easy.
Your URL for listing IdPs looks something like this:
https://[your_namespace].accesscontrol.windows.net:443/v2/metadata/IdentityProviders.js?protocol=wsfederation&realm=[your_realm]&reply_to=[configured_return_url_for_your_rp]&context=&request_id=&version=1.0&callback=
This is the most complete request for list of Identity Providers. Your may miss some variables (such as context, or reply_to), but what I show is the complete request.
So now you have two options:
inclide your own reply_to parameter. It must be withing the configured realm. So if your realm is https://www.mygreatapp.com/, your default return URL would probably be something like https://www.mygreatapp.com/returnUrl/ (if your controller to handle ACS response is returnUrlController. Now, you can safely change the reply_to to be https://www.mygreatapp.com/returnUrl/?foo=bar, just make sure you URL Encode the query string.
Use the context parameter. It is safer to use and I would suggest using it. Now your URL for fetching list of IdPs will be something like:
https://[your_namespace].accesscontrol.windows.net:443/v2/metadata/IdentityProviders.js?protocol=wsfederation&realm=[your_realm]&reply_to=[configured_return_url_for_your_rp]&context=[your_custom_string_value_which_you_may_even_encrypt]&request_id=&version=1.0&callback=
Note the now there is context value present in the request for IdP list ([your_custom_string_value_which_you_may_even_encrypt]). In your returnUrl handler controller, you can check for it with code similar (or equal) to the following:
if (ControllerContext.HttpContext.Request.Form["wresult"] != null)
{
// This is a response from the ACS - you can further inspect the message if you will
SignInResponseMessage message =
WSFederationMessage.CreateFromNameValueCollection(
WSFederationMessage.GetBaseUrl(ControllerContext.HttpContext.Request.Url),
ControllerContext.HttpContext.Request.Form)
as SignInResponseMessage;
if (!string.IsNullOrWhiteSpace(message.Context))
{
// do whatever you want with the context value
}
}
You may want to perform any/more additional checks while handling the SignInResponse from ACS.

Categories