how to get js POST in asp.net webform? - c#

I know its a rudimentary questions, but I am out of practice on webforms. I am using Stripe.js for the first time, and want to use it in conjunction with stripe.net to process the client side. Here is the client code:
<%# Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true"
CodeBehind="StripePage.aspx.cs" Inherits="StripePage.StripePage" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<script type="text/javascript" src="https://js.stripe.com/v2/"></script>
<script type="text/javascript">
// This identifies your website in the createToken call below
// You need to put your real publish key here.
Stripe.setPublishableKey('pk_test_1nDJ3hA1Mv2Sy9bUoYcBMXmm');
// ...
// I am using jquery to process the payment. It knows what form to
// process it on based on the name 'payment-form'
jQuery(function ($) {
//payment submission
$('#payment-form').submit(function (event) {
var $form = $(this);
// Disable the submit button to prevent repeated clicks
$form.find('button').prop('disabled', true);
Stripe.createToken($form, stripeResponseHandler);
// Prevent the form from submitting with the default action
return false;
});
//if there is a error, it is displayed on the page if there was
//no error this is where it gets sent to the server.
var stripeResponseHandler = function (status, response) {
var $form = $('#payment-form');
if (response.error) {
// Show the errors on the form
$form.find('.payment-errors').text(response.error.message);
$form.find('button').prop('disabled', false);
} else {
// token contains id, last4, and card type
var token = response.id;
// Insert the token into the form so it gets submitted to the server
$form.append($('<input type="hidden" name="stripeToken" />').val(token));
// and submit
$form.get(0).submit();
}
};
});
</script>
<form method="POST" id="paymentForm" runat="server">
<span class="payment-errors" runat="server"></span>
<div class="form-row">
<label>
<span>Card Number</span>
<br />
<input id="number" type="text" data-stripe="number" clientidmode="Static" />
<input type="text" size="20" data-stripe="number" runat="server" />
</label>
</div>
<div class="form-row">
<label>
<span>CVC</span>
<br />
<input type="text" size="4" data-stripe="cvc" runat="server" />
</label>
</div>
<div class="form-row">
<label>
<span>Expiration (MM/YYYY)</span>
<br />
<input type="text" size="2" data-stripe="exp-month" runat="server" />
</label>
<br />
<input type="text" size="4" data-stripe="exp-year" runat="server" />
</div>
<asp:Button ID="submit" ClientIDMode="Static" runat="server" Text="SubmitPayment" OnClick="submit_Click" />
</form>
</asp:Content>
The last call in JS creates a JSON object that I want to know how to get to on the C# page on the button click:
protected void submit_Click(object sender, EventArgs e)
{
....
}
I am wanting to do the javascript implementation to avoid having to do PCI compliance. Am I approaching this incorrectly? Should it be all Stripe.net to process everything, and skip the js entirely? Or if this is right, how can I get the form post data in the button click event?

Thanks for the tips in the comments. After much perusal of the internet and hair pulling, I walked away for a bit and came back with this solution.
Made the button just a standard html input (not the asp:Button)
Got the posted back information that was being sent via the JavaScript in the Page_Load event like so
Code Behind:
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
StripeConfiguration.SetApiKey("[API Secret Key");
NameValueCollection nvc = Request.Form;
string amount = nvc["amount"];
var centsArray = amount.Split('.');
int dollarsInCents = Convert.ToInt32(centsArray[0]) * 100;
int remainingCents = Convert.ToInt32(centsArray[1]);
string tokenId = nvc["stripeToken"];
var tokenService = new StripeTokenService();
StripeToken stripeToken = tokenService.Get(tokenId);
var myCharge = new StripeChargeCreateOptions
{
TokenId = tokenId,
AmountInCents = dollarsInCents + remainingCents,
Currency = "usd"
};
var chargeService = new StripeChargeService();
StripeCharge stripeCharge = chargeService.Create(myCharge);
}
}
Seems like using the NameValueCollection (which lives in System.Collections.Specialized namespace) gave me the ability to grab what I needed from the Request.Form by pulling it out via variable name. Since I new the variable names, it was simply a matter of grabbing them and then following the Stripe .NET library documentation to get the token and process the payment.

I want to just post a comment to the answer, but I'm not allowed to yet. So, this isn't really an answer, more of a response to the OP's own findings.
I'm doing the exact same thing, using Stripe.js. I can simply grab stripeToken using Request.Form, and get all other non-c/c-related fields the usual way in the code-behind (e.g. int Total = PaymentTotal.Value;); but what I'm noting isn't so much about grabbing the data, it's that you have to handle it on Page_Load (or during some later point in the page life cycle), because the Submit button's onclick event is never actually fired, since the form is actually submitted using js and not the button.
So, being all literal and kinda answering the original question, you can't actually get the data in the button click event, w/o firing that event manually on postback (I'm surmising).
Hopefully save someone else some time figuring that out if they come here looking to make Stripe and .NET work together.

Related

How to pass textbox value using #Url.Action in ASP.NET MVC Core 2.2

In my View i have the following code:
<input type="text" id="createdDate" placeholder="dd/mm/yyyy" />
Download
In my Control i have de following code:
[HttpGet]
public async Task<IActionResult> GetRoomAccessHistory(DateTime createdDate)
{
// TO DO
}
In this particular case, i want to pass the createdDate value that is inside the textbox (createdDate) to my Url.Action(...), so it could be passed as a queryString in my URL.
This action is invoked as a GET request, and in GetRoomAccessHistory control method, i should get my createdDate.
Thank you.
PS
I think the solution should be something like this:
<a href="#Url.Action("GetRoomAccessHistory", "Files", new { createdDate = ??? })" >Download</a>
I have got a possible answer:
<form method="post" enctype="multipart/form-data" asp-action="GetRoomAccessHistory" id="formGetRoomAccessHistory">
...
<button type="button" id="downloadRoomAccessHistory"</button>
</form>
<script>
var form = document.getElementById("formGetRoomAccessHistory");
document.getElementById("downloadRoomAccessHistory").addEventListener("click", function () {
form.submit();
});
</script>
This does exactly what i want and it works, but i was trying to find a more nice solution because my experience in ASP.NET MVC is low.
You're using the wrong tool for the job.
Since the Url.Action() helper runs on the server-side, it has already executed when the page was first loaded, and generated a fixed URL which is inserted into the page's HTML. It cannot know what the user later enters into the textbox.
If you want to capture data which a user has entered, it makes more sense to use a form. In this case I've used the BeginForm tag helper to generate a suitable HTML <form> tag:
<form asp-action="GetRoomAccessHistory" asp-controller="Files" method="get">
<input type="text" id="createdDate" name="createdDate" placeholder="dd/mm/yyyy" />
<input type="submit" value="Download"/>
</form>
When submitted, this will generate a GET request to the GetRoomAccessHistory action's URL, and append createdDate as a querystring variable, using the value from the textbox.
For Get request,try to use window.location.href.
<input type = "text" id="createdDate" placeholder="dd/mm/yyyy" />
<a onclick = "navigate()" >
< input type="button" value='Download' />
</a>
<script type = 'text/javascript' >
function navigate()
{
var createdDate = document.getElementById('createdDate').value;
var url = "/Files/GetRoomAccessHistory?createdDate=" + createdDate;
window.location.href = url;
}
</script>
And your solution could be simplified to
<form method = "get" asp-controller="Files" asp-action="GetRoomAccessHistory" id="formGetRoomAccessHistory">
<input type = "text" name="createdDate" placeholder="dd/mm/yyyy" />
<button type = "button" onclick="myFunction()">Download</button>
</form>
<script>
function myFunction()
{
document.getElementById("formGetRoomAccessHistory").submit();
}
</script>

Send info to code behind without postback

First, I'm a student, though this is not for school. I'm trying to create a contact us page for my church's website (http://fpcoakwood.azurewebsites.net). I haven't published the contact page yet, as I'm trying to build it. I'm using Bootstrap/jQuery/ASP.NET to build the site. There is a videos page that uses ASP to get the list of videos from YouTube for our channel, and then populates the select html element from that, and I have it working so that selecting a different video loads that video into the player without a postback (though I do wish I could make the back button take me back to the prior page, rather than cycling through prior videos first).
On this page, my challenge is that I'm trying to send an email. I have the code behind working so that I can send the email, but I'm also trying to disable the send button and fadeIn a result div, which would show either success or failure to send the email. The problem is that because the postback occurs, the page reloads, and I lose the disabling of the button and the showing of the status.
Here's some of the code I have so far:
HTML:
<div class="form-group">
<asp:Button class="btn btn-success" ID="sendMail" OnClick="sendMail_Click" OnClientClick="sendMail(); return false;" runat="server" UseSubmitBehavior="false" Text="Send Message" />
</div>
<div id="sendSuccess" runat="server">Success!</div>
<div id="sendFailed" runat="server">Unable to send message. Please try again later.</div>
JS:
$("#sendMail").click(function (event) {
event.preventDefault();
$("#sendSuccess").fadeOut();
$("#sendFailed").fadeOut();
$("#sendMail").attr("disabled", true);
$("#sendMail").attr("text", "Sending...");
return true;
});
C#:
protected void sendMail_Click(object sender, EventArgs e)
{
//sendMail.Enabled = false;
//sendMail.Text = "Sending...";
SendMessage();
}
If I get rid of the javascript function, I can send the email. It goes through no problems. But with the javascript function, the breakpoint in the C# function is never hit, so it's not hitting the server. What I want is to be able to validate in js before sending to the server, then send to the server without a postback, and have the server send a message to the js allowing either the fail or the success message div to fadeIn().
Any help will be VERY much appreciated. Thanks in advance!
The jquery function runs before the C# code behind and interfere with it's result.
To do what you want you could do all the work on the server-side.
You can use ajax to do that.
Use an updatepanel around the controls and an updateprogress with the "sending..." message. Capture the sendmessage() result and then show the #sendsuccess or #sendFailed according to it.
I ended up using the answer in this post (How to call code behind method from a javascript function?) to do what I wanted to do. Surely it could have been done with Filipe's answer, but at this point, I'm already drinking from a fire hose trying to learn what I can learn, so this was easier for me, since I already have a fair understanding of all of the pieces involved.
Here's my HTML:
<form runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePageMethods="true"></asp:ScriptManager>
<div class="col-md-8 col-md-offset-2" runat="server">
<div class="form-group">
<label for="userName">Your name (requrired):</label>
<input type="text" class="form-control" id="userName" runat="server" />
</div>
<div class="form-group">
<label for="email">Email address (required):</label>
<input type="email" class="form-control" id="email" runat="server" />
</div>
<div class="form-group">
<label for="message">Message:</label>
<textarea class="form-control" id="message" rows="5" runat="server"></textarea>
</div>
<div class="form-group">
<asp:Button class="btn btn-success" ID="sendMail" runat="server" OnClientClick="sendMail(); return false;" UseSubmitBehavior="false" Text="Send Message" />
</div>
<div id="sendSuccess" runat="server">Your message has been sent. Thank you for contacting First Pentecostal Church of Oakwood. You are important to us!</div>
<div id="sendFailed" runat="server">Unable to send message. Please try again later. You are important to us!</div>
</div>
</form>
There is an error in the HTML, as the OnClientClick doesn't find the function, but without it and the return false, the page does a postback. I'm not sure how to fix it, as the preventDefault() in the JS doesn't solve it, and using the UseSubmitBehavior by itself doesn't do it, either. But this works, though it shows as an error in the developer tools in the browser.
Here's the CSS:
#sendSuccess,
#sendFailed {
display:none;
border: 1px solid black;
border-radius: 5px;
padding: 5px;
}
#sendSuccess {
background-color: rgba(147, 197, 75, .7);
}
#sendFailed {
background-color: rgba(201, 48, 44, .7);
}
Here's the JavaScript:
//Set up event handler for send message contact page button
$("#sendMail").click(function (event) {
event.preventDefault();
sendMail();
});
//above is in the $(document).ready function
function sendMail() {
$("#sendSuccess").fadeOut();
$("#sendFailed").fadeOut();
$("#sendMail").prop("value", "Sending...");
$("#sendMail").attr("disabled", true);
var name = $("#userName").val();
var email = $("#email").val();
var msg = $("#message").val();
PageMethods.SendMessage(name, email, msg, onSuccess, onError);
}
function onSuccess(result) {
if (result) {
$("#sendSuccess").fadeIn();
$("#userName").prop("value", "");
$("#email").prop("value", "");
$("#message").prop("value", "");
$("#sendMail").prop("value", "Send Message");
$("#sendMail").attr("disabled", false);
}
else { onError(result); }
}
function onError(result) {
$("#sendFailed").fadeIn();
$("#sendMail").prop("value", "Try Again");
$("#sendMail").attr("disabled", false);
}
And here's the C#:
[System.Web.Services.WebMethod()]
public static bool SendMessage(string user, string email, string msg)
{
string to = "xxxxxxxxx#outlook.com";
string from = "xxxxxxxxxx#outlook.com";
string subject = "Message from OakwoodFPC.org Contact Page";
string body = "From: " + user + "\n";
body += "Email: " + email + "\n";
body += msg;
MailMessage o = new MailMessage(from, to, subject, body);
NetworkCredential cred = new NetworkCredential("xxxxxxxxxx#outlook.com", "password");
SmtpClient smtp = new SmtpClient("smtp.live.com", 587);
smtp.EnableSsl = true;
smtp.Credentials = cred;
try
{
smtp.Send(o);
return true;
}
catch (Exception)
{
return false;
}
}

How to enter data in textbox and click on button in someones website programmatically

I have to scrap data from website, i can do this using Import.io but i have to learn that how can i do by write simple program in C#.
Assume that page contain One textbox and one button , and when click on button its give search result .
Page1 : www.example.com
Search : <input type="text" value="abc" id="search" >
<input type="submit" id="submit">
Page2: www.example.com/result.aspx
<body>
<p>you have entered abc</p>
</body>
Now i want only data of result.aspx when i run my localhost:5585/deafult.aspx.
Thanks in advance
You need to pass the data which has been input in page 1 to page 2 somehow. The simplest way would be to use a query string parameter.
Update your Page 1 mark up to use server controls:
<asp:TextBox ID="search" runat="server" />
<asp:Button ID="submit" runat="server" OnClick="btnSubmit_OnClick" />
Create a click event for the submit button:
protected void btnSubmit_OnClick(Object sender, EventArgs e)
{
var redirectUrl = string.Format("/result.aspx?input={0}", search.Text);
Response.Redirect(redirectUrl);
}
Then in Page 2, on page load you want to grab this from the query string:
protected void Page_Load(Object sender, EventArgs e)
{
var input = Request.QueryString["input"];
if (!string.IsNullOrEmpty(input))
{
litResult.Text = input;
}
}
You'll need to update your Page 2 mark up slightly also:
<body>
<p>you have entered <asp:Literal ID="litResult" runat="server" /></p>
</body>

hiding an asp.net generated <span> breaks my javascript form validation

so I am using javascript to validate an address field simply to pull the zip code off the end.
I have two asp:Labels that I show and hide to inform the user. It works great, the labels show when needed and the validation works how I want it, the problem comse when I try to hide them. One of the labels shows and hides just fine, but whenever I try to hide the other the script breaks
<script>
function isvalid()
{
var zip = MainContent_tbx_Appt_Address.value.slice(-5);
if (zip == "") {
MainContent_lbl_Add_validate2.hidden = true;
MainContent_lbl_Add_Validate.hidden = false;
}
else if (!zip.match('[0-9]{5}')) {
//MainContent_lbl_Add_validate.hidden = true;
MainContent_lbl_Add_validate2.hidden = false;
}
else
{
//MainContent_lbl_Add_validate.hidden = true;
MainContent_lbl_Add_validate2.hidden = true;
}
}
</script>
<asp:Label ID="lbl_Add_Validate" style="z-index:100;" Name="lbl_Add_Validate" DataPoint="dp_Add_Validate" runat="server" hidden="true" Text="Address is required"></asp:Label>
<asp:Label ID="lbl_Add_validate2" style="z-index:100;" Name="lbl_Add_Validate2" DataPoint="dp_Add_Validate2" runat="server" hidden="true" Text="Invalid address format"></asp:Label>
<br />
<asp:TextBox ID="tbx_Appt_Address" onblur="isvalid()" style="z-index:100;" Name="tbx_Appt_Address" DataPoint="dp_Appt_Address" runat="server" Rows="4" TextMode="MultiLine" Height="65px" Width="200px" value="Address" onFocus="if (this.value == this.defaultValue) { this.value = ''; }" placeholder="Address">Address</asp:TextBox>
this is my code in my asp file and when it hits the client side it spits out this
<span id="MainContent_lbl_Add_Validate" name="lbl_Add_Validate" datapoint="dp_Add_Validate" hidden="true" style="z-index:100;">Address is required</span>
<span id="MainContent_lbl_Add_validate2" name="lbl_Add_Validate2" datapoint="dp_Add_Validate2" hidden="true" style="z-index:100;">Invalid address format</span>
<br/>
<textarea name="ctl00$MainContent$tbx_Appt_Address" rows="4" cols="20" id="MainContent_tbx_Appt_Address" datapoint="dp_Appt_Address" value="Address" onfocus="if (this.value == this.defaultValue) { this.value = ''; }" placeholder="Address" onblur="return isvalid()" style="height:65px;width:200px;z-index:100;">Address</textarea>
everything else works as long as I have MainContent_lbl_Add_validate.hidden = true; commented out, but if I have ether of them run it breaks
In aspx pages if you are not using jQuery, try to get elements using document.getElementById('MainContent_tbx_Appt_Address'), and if you are using microsoft ajax frameworks you can use $get('MainContent_lbl_Add_validate'), these are the right ways to refer elements on DOM.
Editing: ok, looking your code with more accuracy I saw that you made a mistake on span ids, specifically at 'V' char. Check the case on ids and your script will run.
If you hide an element that has "runat=server", you might think that ASP will render the control styled so that it is invisible-- meaning you can later unhide it using Javascript. That's not how it work. If you set hidden=true, the element isn't rendered at all. Your Javascript is gagging on the reference to the missing element and halting execution, so your valiator code doesn't ever get a chance to run.
To render a hidden element, mark it up like this:
<asp:Label ID="lbl_Add_Validate" style="z-index:100;" Name="lbl_Add_Validate" DataPoint="dp_Add_Validate" runat="server" style="visibility: hidden" Text="Address is required"></asp:Label>
Personally I would let JQuery handle this, which you can do in .aspx:
$(function () {
$('#tbx_Appt_Address').blur(function(){
var text_input = $('tbx_Appt_Address').val();
//additional logic with conditions
if (text_input=='')
{
$('lbl_Add_Validate').show();
}
//etc etc
});
});

Why is the data from my html form not submitting?

I am developing asp.net mvc application. I have a section on the form where I add some text boxes dynamically when the user clicks a "Add New Part" button. The problem is when I submit the form I don't get the data from the fields I added dynamically. I am passing the FormCollection to my controller and stepping through the code in the debugger and those fields are not there. If I look at them in firebug I see them just fine. Any ideas?
Here is the javascript for adding the text fields to the page:
function moreFields() {
var newFields = document.getElementById('readrootpu').cloneNode(true);
newFields.id = '';
newFields.style.display = 'block';
var newField = newFields.childNodes;
for (var i = 0; i < newField.length; i++) {
var theName = newField[i].name
if (theName)
newField[i].name = theName;
}
var insertHere = document.getElementById('newpartusageitems');
insertHere.parentNode.insertBefore(newFields, insertHere);
}
Here is the html:
<div id="readrootpu" class="usedparts" style="display: none">
<% var fieldPrefix = "PartUsage[]."; %>
Part ID:
<%= Html.TextBox(fieldPrefix + "ID", "")%>
Serial Number:
<%= Html.TextBox(fieldPrefix + "Serial", "")%>
Quantity:
<%= Html.TextBox(fieldPrefix + "Quantity", "") %>
<input type="button" value="Remove" onclick="this.parentNode.parentNode.removeChild(this.parentNode);" />
</div>
When I inspect the html with firebug it looks fine to me:
Part ID: <input type="text" name="PartUsage[].ID" id="PartUsage[]_ID" value="" />
Serial Number: <input type="text" name="PartUsage[].Serial" id="PartUsage[]_Serial" value="" />
Quantity: <input type="text" name="PartUsage[].Quantity" id="PartUsage[]_Quantity" value="" />
Thoughts?
Verify with Firebug that all the post data is being sent from the page via the "Net" tab.
Also, i agree with Kobi: you need to increment the ID's on the cloned elements so they are unique.
I would suggest you look into jQuery for dynamically creating html elements. I have only just started learning jQuery and its very easy.
The following code demonstrates a simple file upload form that allows the user can add more input elements dynamically. Each time the jQuery adds a new input element, i append a chr to the id attribute so they are all unique. Hopefully this helps you:
The script block for the jQuery.. notice the last part is for the ajax animation. The actual copying code is only those 4 lines from $("#moreFiles").click
<script type="text/javascript">
var counter = "oneFile";
$(document).ready(function() {
$("#moreFiles").click(function() {
var newCounter=counter+"1";
$("p#"+counter).after("<p id='"+newCounter+"'><input type='file' name='"+newCounter+"' id='"+newCounter+"' size='60' /></p>");
counter=newCounter;
});
$("#submitUpload").click(function() {
$("#submitUpload").val("Uploading...");
$("img.uploadingGif").show();
});
});
</script>
..and the aspnet markup:
<% string postUrl = Model.PostUrl + (Model.ModelID > 0 ? "/" + Model.ModelID.ToString() : ""); %>
<form id="uploadForm" class="uploadForm" action="<% =postUrl %>"
method="post" enctype="multipart/form-data">
<label>Select file(s) for upload (size must not exceed
<% =Html.Encode(ServiceConstants.MAX_FILE_UPLOAD_SIZE_INBYTES) %> bytes):</label>
<p id="oneFile"><input type="file" name="oneFile" id="oneFile" size="60" /></p>
<% if(Model.MultipleFiles) { %>
<p><a id="moreFiles" href="#">add more files</a></p>
<input id="MultipleFiles" type="hidden" name="MultipleFiles" value="true" />
<% } %>
<p><%--<input id="submitUpload" type="submit" value="Upload" />--%>
<% =Html.InputSubmit("Upload","submitUpload") %>
<% =Html.LoadingImage("uploadingGif") %>
</form>
..this all only boils down to a few lines of html and jQuery.
When you have multiple values on fields with same names, you should be able to see them on the server side using Request.Form.GetValues("key").
You should note that when you clone the nodes, you create copies with the same IDs, which is considered invalid.
Also, you have a for loop there, and I don't quite get what it does (reads the node's name and sets it back - what is the reason for doing that? Should that be var theName = newFields[i].name ?)
I was working with plain HTML when my form worked fine if all the fields were left blank, but it would not submit if I filled out the form.
Later I realized that it was because of a text-field entry 'Email' in which I was entering an email-address containing the character '#'. When I removed the '#', the form started submitting again.
You cannot just aribtrarily add text boxes client-side without having the corresponding server-side controls ready to read the data from the postback. However, you should be able to read the raw data from HttpRequest.Form.
update: oops! it's MVC. I didn't read^H^H^H^H see that. never mind.
-Oisin

Categories

Resources