Submitting Form to Handler is not working - c#

I am trying to submit a form to a handler page but nothing is working now, it doesn't even hit the handler...
Here is my code :
<form action="Unsubscription.ashx?actionmethod=subscribe" method="get" >
<div class="h1">
<input type="text" class="input" value="enter your e-mail" name="ekey" />
<input type="submit" value="Submit" />
</div>
</form>
handler code :
public void ProcessRequest(HttpContext context)
{
try
{
string email = context.Request.Params["ekey"];
switch (context.Request.Params["actionmethod"])
{
case "subscribe":
NewsLetter.Subscribe(email);
break;
case "unsubscribe":
NewsLetter.Unsubscribe(email);
context.Response.ContentType = "text/html";
context.Response.Write("your subscription has been successfully canceled. thanks.<br/><a href='http://www.kayatax.com'><b>home page</b></a>");
break;
}
}
catch {
context.Response.ContentType = "text/html";
context.Response.Write("This e-mail doesn't exist in our database. Thanks.<br/><a href='http://www.kayatax.com'><b>Home Page</b></a>");
}
}

Your </<form> tag is malformed for a start. Make it </form>, as I'm sure you know.

If you have browser-side rendering problems, and you're not hitting your server-side handler, I'd investigate the browser side first. See what is getting transmitted over the wire: in Firebug, enable the Net panel, reload the page, submit the form and then look at the Request in the Net panel. Hover over the first node (the request to the form-handler page) and make sure the request URL is as you expect. Then expand the node and look at the Request headers.
The first thing I'm wondering, not seeing more of your web-app, is whether the target Unsubscription.ashx is in the same directory as the page with the form, or if there's a routing method of some sort that makes it look that way. You're using a document-relative URL; are you sure the target is where you think it is?
By the way, you should not use the GET method for form submissions that change data on the server; use POST for that. It's a bit more work, but much safer. GET requests should be idempotent. If you use GET to trigger an action that changes things on the server, you may find they're changed when you don't expect them to be. D'oh!

Your form is using 'get' which essentially is HTTPGET. Check the submitted URL and querystring. It should be
Unsubscription.ashx?actionmethod=subscribe&ekey=enter%20your%20email
is it showing correctly?
You do not have a name for your input-submit button, but that shouldn't affect what you want.

Related

ASP.NET MVC: How do I change where Ajax.BeginForm will post to after the page loads?

I want to make an Ajax.BeginForm that will by default, go to the add user page. I also want in the same form an edit and delete button. The information in the form will be the same, I just need it to post to the different edit user and delete user URL.
How can I modify where the form will post, depending on what submit button is pressed, while keeping all the items that Ajax.BeginForm gives us.
Edit:
Also wanted to note that I want the URL to be generated by my routes. So in the same way the BeingForm uses the "action" and "controler" to make the path, I want to use that as well when I change the URL, so the URL is dynamic and not static.
I was able to get this to work by using jquery to change the action to the form using Url.Actions.
The HTML button:
<button type="submit" class="btn btn-danger" id="formDeleteButton" onclick="ChangeFormToDelete()">Delete</button>
The javascript/jQuery
function ChangeFormToDelete() {
$('#UserForm').attr('action', '#Url.Action("DeleteUser", "UserManagement")')
}
In #Url.Action the firstparameter is the action and the second is the controller. I made the exact same functions for edit and add and it worked perfectly.

Send Ajax Requests vs Sending Entire Form By Id

The client should be able to send everything with a button, so I can do the following:
Send everything as form fields named like invoiceId_detail_text where invoiceId would be the id of the invoice, detail the part, and text the kind of field.
Example:
<form id="invoices" name="invoice">
#foreach(var Invoce in Model.Invoices) {
<div>
<input type="number" id="#String.Format("{0}_amount", Invoice.InvoiceId)"/>
</div>
/*More Input Fields for the Invoice*/
<div>
<button type="submit"></button>
</div>
}
</form>
Or I can put every invoice separated in its own form, and send them by ajax, every form success I send the next one and so on.
Example:
#foreach(var Invoice in Model.Invoices) {
string formName = String.Format("{0}_form", Invoce.InvoceId);
<form id="#formName" class="invoiceForm" id="#formName" action="#Url.Action("EditIndividualInvoice","InvoicingEdit")">
<input type="hidden" name="InvoiceId" value="#Invoice.InvoiceId"/>
<div>
<input type="number"/>
</div>
/*More Input Fields for the Invoice*/
</form>
}
<button type="button" onclick="SendAllForms();">Send</button>
I did some research between some of my co-workers and many of them told me to just go with a post with all the invoices at the same time and then access every field by item id because I don't have knowledge of how many invoices are going to be sent, but i can get all of them by class on JQuery so it shouldn't be a problem.
I also read this article from a UX point of view and it keeps me thinking about it.
By doing it with AJAX the cliend could be able to see a loading bar and it would be great, but if he closes the page the request would be incomplete and it could be complicated.
Which option could be better and why and what are the security implications of using one over another?
I think the solution depends principally of the behavior that you wish.
By doing it with AJAX the cliend could be able to see a loading bar and it would be great, but if he closes the page the request would be incomplete and it could be complicated.
In the 2 solutions, if the user closes the page after clicking the button, this will not cancel the save. Once the request sent, it cannot be cancelled. So you shouldn't have "security" problems whatever the choosen solution.
The only thing you need to be careful, is to disable all AJAX buttons during an AJAX request, to avoid the user sending several request in the same time (that can provoke saving inconsistency data).
The classic solution is generally most simple to implement.
The AJAX solution can be most complicated to implement (more code), but provides a friendliest behavior.

Invalid ViewState when using jQuery tabs

I have a fairly simple page with a set of jQuery tabs, the content of some is called via ajax. I also have a search box in the masterpage in my header.
When I open the tabbed page the search box works fine. However once I have clicked on one of the ajax tabs the search box fails to work with an "Invalid Viewstate" yellow screen of death.
I believe this is because the ajax page is replacing the __VIEWSTATE hidden input with its own.
How can I stop this behaviour?
UPDATE: I have noticed that the YSOD only appears in IE and Chrome, Firefox doesn't seem to have the same issue. Although how the browser influences the ViewState, I'm not sure.
UPDATE: I've put a cut down version of the site that shows the issue here: http://dropbox.com/s/7wqgjqqdorgp958/stackoverflow.zip
The reason of such behavior is that you getting content of the ajaxTab.aspx page asynchronously and paste it into another aspx page. So you getting two instances of hidden fields with __VIEWSTATE name and when page posted back to server theirs values are mixing (might depends on how browser process multiple controls with same name on submit). To resolve this you can put second tab's content into a frame:
<div id="tabs">
<ul>
<li>Default Tab</li>
<li>ajax Content</li>
</ul>
<div id="tabs-1">
<p>
To replicate the error:
<ul>
<li>First use the search box top right to search to prove that code is ok</li>
<li>Then click the second ajax tab, and search again.</li>
<li>N.B. Chrome / IE give a state error, Firefox does not</li>
</ul>
</p>
</div>
<iframe id="tabs-2" src="ajaxTab.aspx" style="width:100%;" ></iframe>
</div>
Also, I'm not sure but this seems like error in the Web_UserControls_search control. In my opinion, NavBarSearchItemNoSearchItem_OnClick method must be refactored as below:
protected void NavBarSearchItemNoSearchItem_OnClick(object sender, EventArgs e)
{
var searchFieldTbx = NavBarSearchItemNo;
var navBarSearchCatHiddenField = NavBarSearchCatHiddenField;
var term = searchFieldTbx != null ? searchFieldTbx.Text : "";
if (term.Length > 0) //There is actually something in the input box we can work with
{
//Response.Redirect(Url.GetUrl("SearchResults", term));
Response.Redirect(ResolveClientUrl("~/Web/SearchResults.aspx?term=" + term + "&cat=" + navBarSearchCatHiddenField.Value));
}
}
Draw attention that we resolving client url when redirecting to search results page and instead of navBarSearchCatHiddenField use navBarSearchCatHiddenField.Value as cat parameter.
I guess that you use AJAX to fill the content of the tab. So in this case, content of your tab will be replaced by the new one from ajax and certainly _VIEWSTATE will be replaced. At server, do you use data from ViewState? In the "static tabs", you should prevent them auto reload by using cache:true
Your issue is that with your ajax call you bring in a complete ASPX page. Including the Form tag and its Viewstate. If you remove the Form tag from ajaxTab.aspx you will see everything works fine. asp.net does not know how to handle two Form tags in one page. Same goes for hidden Viewstate fields. You cannot bring in a full aspx page via ajax. Just bring in the content Div you want to display and you`ll be good to go.

What does IsPostBack actually mean?

I am interested to know what specifically Page.IsPostBack means. I am fully aware of it's day to day use in a standard ASP.NET page, that it indicates that the user is
submitting data back to the server side. See Page:IsPostBack Property
But given this HTML
<html>
<body>
<form method="post" action="default.aspx">
<input type="submit" value="submit" />
</form>
</body>
</html>
When clicking on the Submit button, the pages Page_Load method is invoked, but the Page.IsPostBack is returning false. I don't want to add runat=server.
How do I tell the difference between the pages first load, and a Request caused by the client hitting submit?
update
I've added in <input type="text" value="aa" name="ctrl" id="ctrl" /> so the Request.Form has an element, and Request.HTTPMethod is POST, but IsPostBack is still false?
Check the Request.Form collection to see if it is non-empty. Only a POST will have data in the Request.Form collection. Of course, if there is no form data then the request is indistinguishable from a GET.
As to the question in your title, IsPostBack is set to true when the request is a POST from a server-side form control. Making your form client-side only, defeats this.
One way to do this is to extend the ASP.NET Page class, "override" the IsPostBack property and let all your pages derive from the extended page.
public class MyPage : Page
{
public new bool IsPostBack
{
get
{
return
Request.Form.Keys.Count > 0 &&
Request.RequestType.Equals("POST", StringComparison.OrdinalIgnoreCase);
}
}
}
In the example that you include in your question, there is no viewstate involved; there is no way for the server to link this request to a previous request of the page and treat them as a unit. The request resulting in clicking the button will look like any other random request coming in to the server.
Generally a you could view a PostBack as a combination of:
HTTP request method equals "POST"
HTTP header HTTP_REFERER equals the current URL
That's not 100% foolproof tho, it does not take into account any state of any kind (which you probably want even if you don't know it) but it is a post, back to the current page.
You could check the headers to see if your input controls are returning a value (using Request.Forms as tvanfosson points out). However, the really big question is why you would not want to add runat=server. The entire page processing edifice implemented by ASP.NET (except MVC) depends on processing the page output through the server to set up the appropriate client-side code for callbacks, etc.

What does the Request object do in the following scenario?

If I see something like:
if(Request["Email"])
{
}
What does this actually mean? Where is the Email collection member actually being set?
It's retrieving the variable from get/post parameters.
somepage.aspx?blah=1
string blahValue = Request["blah"];
Console.WriteLine(blahValue);
> 1
Even more specificially:
Cookies, Form, QueryString or ServerVariables
http://msdn.microsoft.com/en-us/library/system.web.httprequest_members(VS.71).aspx
See this for example.
Taken from the above link
All variables can be accessed directly by calling Request(variable) without the collection name. In this case, the Web server searches the collections in the following order:
QueryString
Form
Cookies
ClientCertificate
ServerVariables
It retrieves either the submited form values (POST) or the submitted querystring values (GET).
You would generally see it written as either Request.Form["Email"] or Request.Querystring[Email"] instead of just Request["Email"].
Example of Form (POST) method:
On the HTML or ASPX Page:
<form action="SomePage.aspx">
<input type="hidden" name="Email" value="someaddress#email.com" />
<input type="Submit" value="Submit Form" />
</form>
Once the form has been submitted by clicking the Submit Form button you would retrieve the form values using Request.Form["Email"] (or just Request["Email"] for the lazy :))
Just some additions to the posts of the others.
To have things more explicitly you normally use Request.QueryString[...] for getting values from the QueryString, so when a GET request has been done and Request.Form[...] when a POST request is done. Although in the latter case you usually directly access the values of your server controls, since ASP.net uses the ViewState mechanism to load back on your controls when the request comes back from the client.

Categories

Resources