I have two websites A and B both written in ASP.NET MVC 3. In website A there is a form which needs to be submitted to website B via POST method. The user has option to post it directly or after encrypting the values.
When I submit form without encryption it is simple form.submit() and I am able to get the values in website B using FormCollection object. But when user selects submit after encryption, I redirect to another action on website A itself where encryption occurs and then this encrypted data is placed in a hidden textbox in the corresponding view and then auto submitted on page load using jQuery to website B. But now I am unable to get any values in FormCollection object on website B.
What could the problem be? Is this happening because of any security feature to prevent XSS or something similar?
Its doubtful its from XSS protections - in that case you would see an exception.
Load up fiddler and make sure you see this data in an element inside your form that is getting posted to website b. if its there in the form that is being submitted - it should be available.
Any reason for not using HTTPS and submitting directly the form to site B?
<form action="https://siteb/someaction" method="POST">
<input type="text" name="key1" value="value1" />
<input type="text" name="key2" value="value2" />
<input type="text" name="key3" value="value3" />
<input type="submit" value="Go ahead" />
</form>
If there is any reason in the case you are encrypting the values into a single hidden input and submitting the form containing this hidden field using javascript, only the value of the hidden field will be sent to site B. So for example if you had the following form:
<form action="http://siteb/someaction" method="POST">
<input type="hidden" name="encrypted" value="some encrypted value" />
</form>
on site B you would fetch the encrypted value like this (don't use FormCollection, it's kinda ugly compared to view models):
[HttpPost]
public ActionResult SomeAction(string encrypted)
{
// TODO: decrypt the encrypted value here to get the orginal string
...
}
And an even more elegant way would be to have a view model defined on site B and a custom model binder for this model that will do the decryption so that the action looks simply like this:
[HttpPost]
public ActionResult SomeAction(SomeViewModel model)
{
// Directly use the model with all the fields in it.
// The custom model binder will take care of the creating it
// from the encrypted request string
...
}
Related
I need my app to allow POST requests from anywhere without throwing a 400 Bad Request error. I am using <form action='/anotherurl' method='post'> and need to be able use the parameters passed through POST on another page in my application. Note: I cannot use GET because I do not want the parameters visible in the URL.
I have tried adding #attribute [IgnoreAntiforgeryToken] to the page but that did not work. Is there a way to force Blazor to allow for the POST request to go through?
Edit: Here is the entire form
<form action="/ClientReports" method="post" target="_blank">
#foreach (var id in SelectedClientIds)
{
<input type="hidden" id="Params" name="Params" value="#id">
}
<input type="submit" value="Client Reports">
</form>
The parameters are added to hidden inputs and then submitted like a normal HTML form but when the navigation occurs the result is a 400 error. The same code with a GET request does work.
Adding #attribute [IgnoreAntiforgeryToken] to the _Host.cshtml file will allow HTML forms to POST to a Blazor Server app.
Note: Since Blazor is a SPA this will turn off Anti-forgery globally, more code is required to turn it off for individual pages.
I have a form like so:
<form action="#Model.AuthUrl" method="GET" class="login-bottom">
<p>
<input type="hidden" name="response_type" value="code" />
<input type="hidden" name="client_id" value="Model.AppKey" />
<input type="hidden" name="redirect_uri" value="#Model.RedirectUri" />
<input type="hidden" name="state" value="#ViewBag.State" />
<input type="hidden" name="ReturnUrl" value="#ViewBag.ReturnUrl" />
<button type="submit" class="btn btn-primary">Click Here</button>
</p>
</form>
And we use it in our app to perform third-party OAuth authentication. This works fine. However, we occasionally run into a problem with the #ViewBag.State variable. This variable holds a value we generate in order to prevent cross-site forgery. So we validate this value when the third party directs us back to the #Model.RedirectUri (hosted in our domain).
The problem occurs when this page has been sitting on the user's screen for more than 20 minutes (we store the #ViewBag.State variable in the Session for later validation, which expires after 20 minutes). Basically, the state variable in the session becomes stale.
After the client authenticates and is redirected back to our site, we check the state value, and if it's been 20 minutes, that value is gone, so our system generates an error and directs them to authenticate again.
I would like to be able to pass the form variables to the third party auth page dynamically, right as the user clicks the button. My first thought is to wrap this in a controller and do a return Response.Redirect(); to the third party auth page. However, the third party auth requires that we pass in those variables you see in the form via application/x-www-form-urlencoded params, and I can't seem to find a way to pass those variables in that manner. Is there a way to pass these variables in that manner via a Response.Redirect?
Or is there a better way to handle this flow so that I don't allow the state variable to get stale? (preferrably without client-side scripts)
I am passing the input data from the .cshtml page to the action method.
Here is my .cshtml page:
#model passingdata
<form asp-controller="Home" method="post" asp-action="About" >
<button class="btn-danger" type="submit" value="Submit"></button>
<div class="form-group">
<label>
<input asp-for="date" placeholder="Date" class="col-md-8" />
</label>
<label>
Select from these Four Classes
<input type="radio" name="class" asp-for="classselect1" id="classselect1" value="classselect1" class="col-md-4" /> <p> #Model.classname1</p>
<input type="radio" name="class" asp-for="classselect2" id="classselect2" value="classselect2" class="col-md-4" /> <p> #Model.classname2</p>
<input type="radio" name="class" asp-for="classselect3" id="classselect3" value="classselect3" class="col-md-4" /> <p> #Model.classname3</p>
<input type="radio" name="class" asp-for="classselect4" id="classselect4" value="classselect4" class="col-md-4" /> <p> #Model.classname4</p>
</label>
</div>
</form>
And here is my controller code which is invoked when i Click on the button.
[HttpPost]
public IActionResult About(passingdata p)
{
ViewData["Message"] = "Your application description page.";
Teacher.classselect1 = p.classselect1;
Teacher.classselect2 = p.classselect2;
Teacher.classselect3 = p.classselect3;
Teacher.classselect4 = p.classselect4;
Teacher.date = p.date;
return View();
}
The input data like date and bool value from the radiobutton is not passing through the object of the class which contain these variables.
Please help me in this.
If i remember correctly, the Name attribute of each radiobutton is how .net MVC will map the values to your model.
In this case, all of your names are "class", which essentially means you have 1 form field named class with 4 options.
I would recommend using the html helper classes, because they will automatically create the proper html for you. The answer to this post should help: When using .net MVC RadioButtonFor(), how do you group so only one selection can be made?
If you dont want to use the helper just remember that when you submit a form, the data that is posted is based on the name of each form field. .Net does some magic in the background to serialize your Model for you, but essentially you are just submitting data in the format "?prop1=val1&prop2=val2".
Update
I figure maybe I should clarify a little better why what you are doing is not working how you expect.
When you post or put data via a form, it passes the input fields (text box, radio button, checkbox, etc...) as either querystring params or are part of the body. Radio buttons work a little differently than other input type. For a radio button, there are multiple input elements, but only one of them is valid. That is handled by using the name attribute. In your case, all of the names are "class", which means that the only thing being passed to the server is a single "?class={val}" (val is the value of which ever radio button is selected).
If your passingdata model had a property called "class", it would be populated. If your goal is to populated all 4 of the classselect properties with different values, you would need the name of each radio button to be different. But if there was only one radio button with each name, then each property could only have 1 value. You would need multiple RadioButtons with the same name to have multiple values (only one of which is selectable for each property).
Hopefully that clarifies what is wrong and gets you in the right direction.
I have a solution that I built using Webforms that passes over approximately 10 fields to the Realex payments processor server (I use the redirect method), and all works fine there. I'm brand new to MVC and am trying to put in place the same functionality using MVC as I currently have set up with Webforms. With my Webforms solution, I use a buttonclick event handler and a Postback URL, to gather the data I need to pass to Realex and the URL is managed in the Postback.
Using MVC, I don't seem to have the use of an event handler or a Postback URL declaration, or if I do, I can only post back to the form, whereas I need to post my data to an external website.
So in my MVC controller, I have hardcoded in the values (for testing purposes), that I am trying to pass to Realex.
The last line above (return Redirect), is bringing me to the Realex page (it is not letting me see the boxes though for entering credit card details, instead it is returning a 506 error saying "Invalid MerchantID or account number)...
I've been onto Realex and they are telling me that they can see the data above that I'm trying to pass to their server, like my account ID, my order reference, etc.
I've also tried doing it this way within my View, just to get this to post properly:
<input id="ORDER_ID" name="ORDER_ID" type="hidden" value="6264286038162642860381" />
<input id="ACCOUNT" name="ACCOUNT" type="hidden" value="XXXXXXXXX" />
<input id="AMOUNT" name="AMOUNT" type="hidden" value="100" />
/>
But I don't know how to hook up my form fields with my controller, I know I'm still thinking "Webforms" here, and am just not thinking MVC, because I've so little experience with MVC and am finding the transition to MVC more difficult than I though.
Thanks in advance for any help with this...
I think you want something like this, I'm sure there's a more elegant solution but this should work.
public ActionResult ShoppingCart(decimal _TotalPriceBox = 1)
{
//After populating your shopping cart model
ViewBag.MerchantId = My_Cart.MYUSERIDSTRING;
ViewBag.Account = My_Cart.ACCOUNT;
ViewBag.OrderId = My_Cart.ORDER_ID;
ViewBag.Amount = My_Cart.AMOUNT;
//Rest of needed properties
return View()
}
Then in the form inside your view
<form action="https://epage.payandshop.com/epage.cgi" method="post">
<input id="ORDER_ID" name="ORDER_ID" type="hidden" value="#ViewBag.OrderId" />
<input id="ACCOUNT" name="ACCOUNT" type="hidden" value="#ViewBag.Account" />
<input id="AMOUNT" name="AMOUNT" type="hidden" value="#ViewBag.Amount" />
//Rest of inputs needed
<input type="submit" value="send" />
</form>
I'm using umbraco with extensionless urls.
I've inserted a simple piece of HTML in one of my masterpages (en/test) :
<form method="post" enctype="multipart/form-data">
<input type="submit" />
</form>
When I press the submit button, I get a 404. The path is exactly the same and should exist.
When I remove the enctype part, the submit occurs fine.
I can't figure out how to fix this, but I bet it has something to do with the rewriting.
I also tried the following without success:
<form method="post" enctype="multipart/form-data" action="/en/test">
<input type="submit" />
</form>
<form method="post" enctype="multipart/form-data" action="/en/test.aspx">
<input type="submit" />
</form>
The only page where I CAN use the enctype attribute, is on the actual homepage. I guess this has to do with the fact that the physic default.aspx exists.
=============== UPDATE =================
There is only one form element in the page, the one that I've inserted. So a "whole page" form element is certainly not the case. Secondly, yes the form is in theory posting back to itself. I also tried an empty action tag, plus an action tag with the full url as suggested, with the same results.
When I either use the following scenario's:
No action attribute
action=""
action="{relative path}"
action="{absolute path}"
I end up on exact same URL as where I fired the submit from. But it's a 404. When I press the enter key in my address bar, no 404, I'm back at my original page with the same URL.
First question I should ask is do you get a 404 when you browse to "/en/test" or "/en/test.aspx". For the form to post back to itself try an empty action e.g. action="" or writing the current url into the action attribute. And one further question, do you have another form wrapped around your page with the runat="server" attribute because if you have you will end up with nested forms which will also cause you issues.
On a side node I would strongly suggest upgrading your installation to at least v4.11.4 due to a bug that was introduced in 4.10. Please see the following for details...
Trying to publish a root node (parent) after unpublishing a child result in a YSOD:
http://issues.umbraco.org/issue/U4-1491
Path Fixup
http://our.umbraco.org/projects/developer-tools/path-fixup