The case
I have two web forms, and some codebehind. The first webform is a formular where I enter a string. I want to send that string to the second formular using a post method, and display it.
The problem
I am getting an error message, saying the MAC Viewstate could not be validated :
Erreur du serveur dans l'application '/'. Échec de la validation MAC
Viewstate. Si cette application est hébergée par une batterie de
serveurs ou un cluster, assurez-vous que la configuration
spécifie le même validationKey et le même algorithme de validation.
AutoGenerate ne peut pas être utilisée dans un cluster.
What am I doing wrong ?
Webform1.aspx
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication1.WebForm1" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
</head>
<body>
<form id="form1" runat="server" action="WebForm2.aspx" method="post">
<div>
Enter your first name : <input type="text" name="FirstName"/><br />
<input type="submit" />
</div>
</form>
</body>
</html>
Webform2.aspx
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm2.aspx.cs" Inherits="WebApplication1.WebForm2" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
First name : <%= FirstName %>
</div>
</form>
</body>
</html>
Webform2.aspx.cs
public partial class WebForm2 : System.Web.UI.Page
{
public string FirstName { get; private set; }
protected void Page_Load(object sender, EventArgs e)
{
FirstName = Request.Form["FirstName"];
}
}
Note : I have very little experience with web technologies, and I'm trying to learn asp.net and html, so please forgive me.
EDIT 1 :
WebForm3.aspx
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm3.aspx.cs" Inherits="WebApplication1.WebForm3" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
</head>
<body>
<form id="form1" runat="server">
<%if (!IsPostBack){ %>
<div>
Enter your first name :
<input type="text" name="FirstName" /><br />
<input type="submit" />
</div>
<% } else { %>
<div>
First name : <%= FirstName %>
</div>
<% } %>
</form>
</body>
</html>
WebForm3.aspx.cs
public partial class WebForm3 : System.Web.UI.Page
{
public string FirstName { get; private set; }
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
FirstName = Request.Form["FirstName"];
}
}
}
WebForm1.aspx (revised)
<form id="form1" runat="server" method="post">
<div>
Enter your first name : <input type="text" name="FirstName"/><br />
<asp:Button PostBackUrl="~/WebForm2.aspx" Text="Validate" runat="server"/>
</div>
</form>
WebForm3.aspx is working fine, and the WebForm1 using an asp:Button is also working, thank you very much.
Additional question :
The purpose of this test was to look for other ways to send data in a "common" way (the post method, since "they" said it is the most secure way). Now, I am only left with one question : what is the best practice, using two files (WebForm1 and WebForm2 method), or a single file (WebForm3 method) ? In other words, should the same page be responsible for gathering data and treating them, or should those responsabilities be split into two files ?
EDIT 2, and last question
When using two files, I see that the IsPostBack property is equal to false. When using a single file, I see that the IsPostBack property is equal to true, when submitting. Is that property only changing (and therefore useful) when using a single file ?
Webform1.aspx
<form id="form1" runat="server" action="WebForm2.aspx" method="post">
Assuming I understood what you're trying to accomplish - if you want to override the PostBack mechanism of WebForms, an easy way is to use PostBackUrl with a Button control.
It's how ASP.Net WebForms work (postback to same page). There are other ways of POSTing to another WebForms Page, but try the PostBackUrl first and see if that's all you really need (least amount of resistance).
You can look into ASP.Net MVC or WebPages too, if you want to use more "standardized" way of doing things (like simply wanting to POST to a resource of your choosing) as what I think you want to accomplish.
Hth...
Update
Well, you won't like my answer because "it depends" -
the "common way" in ASP.net WebForms is really same page - the default PostBack mechanism, and then you'd handle display much like you did above - but through controls (e.g. Placeholder or user controls).
you can also look into things like Wizard controls -> useful for those cases where you need to guide a user through Steps - e.g. perhaps an application form that is lengthy and you want to cut it up into more manageable steps - to cobble this up on your own in a single Page using the Postback mechanism, or even multiple Pages (cross-page Posting) while doable, is probably an exercise in self-punishment :)
there are other ways, but I don't want to confuse and stay on topic (e.g. AJAX).
I'll hold off on "security" because you'll need to be more specific about that - and maybe deserves a separate question. In general the operative rule is "don't trust the client" (meaning validate all data any/all clients provide your application), server-side - not just client-side validation (they should work hand in hand, not mutually exclusive).
Hth...
Update 3
When using two files, I see that the IsPostBack property is equal to false. When using a single file, I see that the IsPostBack property is equal to true, when submitting. Is that property only changing (and therefore useful) when using a single file ?
IsPostBack means "Did this POST request come from myself"?
Page1.aspx -> Button.PostBackUrl -> Page2.aspx = IsPostBack is false
Page1.aspx -> Any button/control that triggers a postback = IsPostBack is true
Having said that, "only useful" - in this simple example perhaps. But you can use that check for other things - you mentioned security earlier, so you can check whether or not your page can/will/should accept a POST request coming from anywhere.
In your sample case, the target page of the POST (when using 2 pages and PostBackUrl) should check/validate the POST data it is receiving - because anyone can do the same thing you just did (POST to it).
Related
I am working on a project in C# .NET that allows me only one form in the .aspx file.
<form id="form1" runat="server" action="#1">
How can I change the form action through the C# code in a method?
I have tried this:
protected void Button1_Click(object sender, EventArgs e)
{
form1.Action = "#2";
}
but it didn't work. Thanks in advance...
Based on the comments to you question. asp:Panel Controls could help you out.
A very rough example
ASPX:
<form id="form1" runat="server">
<asp:Panel id="Form1" runat="server">
<!-- Form 1 Stuff -- >
<asp:Button ID="Button1" runat="server" Text="Submit"
OnClick="Button1_Click" />
</panel>
<asp:Panel id="Form2" runat="server" Visible="false">
<!-- Form 2 Stuff -- >
<asp:Button ID="Button2" runat="server" Text="Submit"
OnClick="Button2_Click" />
</panel>
</form>
C#
protected void Button1_Click(object sender, EventArgs e)
{
//HIde "Form"1
Form1.Visible = false;
//Show "Form"2
Form2.Visible = true;
//Do other stuff
}
protected void Button2_Click(object sender, EventArgs e)
{
//Do Final Processig
}
Also look at the DefaultButton property of the Panel
(Moving this to the top because it's an answer to the newly understood question. It's not how to change the form action, but how to have multiple forms.)
If you want a server form on a page that already has a server form then perhaps that second "form" should be a User Control. That way it sits inside the host page's server form but doesn't require its own form. And it's self-contained, able to contain whatever logic it needs when handling a postback.
Here's an example of a simple User Control. You can create one from Add > New Item > Web > Web Forms User Control.
<%# Control Language="C#" AutoEventWireup="true"
CodeBehind="OtherForm.ascx.cs" Inherits="WebApplication1.OtherForm" %>
<label for="<% = OtherFormTextInput.ClientID %>">
This is some other form on the same page
</label>
<asp:TextBox runat="server" ID="OtherFormTextInput"></asp:TextBox>
<asp:Button runat="server" ID="Submit" Text="Submit this other form"/>
It looks like an .aspx page but it has no form. It can still have its own code behind which can interact with with the other server controls it contains, just like an .aspx page would.
Then you add that control to your "main" page:
<%# Page Language="C#" AutoEventWireup="true"
CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication1.WebForm1" %>
<!-- Register the user control -->
<%# Register TagPrefix="uc" TagName="other" Src="~/OtherForm.ascx" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<!-- This form has its own stuff, but also contains the "other" form. -->
<uc:other runat="server" ID="TheOtherForm"></uc:other>
</form>
</body>
</html>
I recommend this over using panels (which still works) because if you're putting two forms on one page, it's likely that you might at some point want to move the secondary form to another page or re-use it. This approach keeps it completely self-contained. Its code-behind isn't in the same file as the the .aspx page. You can place this on as many pages as you want.
Original "literal" answer which addresses the question as originally understood.
The runat="server" form exists entirely for the purpose of allowing ASP.NET to interact with the page and its server controls during postbacks. It's central to the way webforms works. If you change the action then technically what you have isn't a webforms page any more.
That's fine (I don't even like webforms) but it can lead to some weird behavior. If you have controls that trigger postbacks then normally they'd be handled on the same page and your user would just see a (hopefully) fast refresh. Now they might get sent to another page.
What if you just removed that form entirely and added your own form instead? Then your .aspx page will just behave more like an .html page.
Having added all the disclaimers about why not to do it, you can change the action using JavaScript. Here's a sample:
<%# Page Language="C#" AutoEventWireup="true"
CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication1.WebForm1" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server" ClientIDMode="Static">
<asp:Button runat="server" text="Causes postback"/>
<asp:CheckBox runat="server" AutoPostBack="True"/>
</form>
<script>
document.getElementById("form1").action = "http://stackoverflow.com";
</script>
</body>
</html>
Some browsers might not allow changing the form's action.
I put the checkbox there just for fun (I must be really bored) to show the odd side effects it could have, that you might click on a checkbox and get redirected to a different page.
You can write a response.write() in your Asp.net side that print some javascript or jQuery code! As #Scott Hannen wrote some javascript like this :
Response.Write("<script>document.getElementById('YOURFORMID').action = 'YOUR URL';</script>");
or with jQuery
Response.Write("<script>$('#YOUR FORM ID').attr('action', 'YOUR URL');</script>");
btw if you have access to .html or .js files u can directly put this jQuery code without any C# code!
I've been doing some really clever stuff (I think) in ASP.Net c#, so much so that the simple stuff is more difficult (if that makes sense)
I have this snippet of code in my page
<form id="form1" runat="server">
<asp:HiddenField runat="server" ID="hdnConfirm" value="Hello World" />
<asp:LinkButton runat="server" PostBackUrl="/confirm.aspx" Text="Confirm">
</asp:LinkButton>
</form>
I have this snippet of code in confirm.aspx.
if !(IsPostback)
{
lblConfirm.Text = Request.Form["hdnConfirm"]
}
I was expecting this to be nice and simple but when i click the button and go to page "confirm.aspx" the Request.Form has no values. What have I missed ?
[TESTING]
I ran a test on a brand new web forms project in VS2013. Dot.Net 4.5.1 This does not work. PreviouPage is always null. Whether surrounded by (!IsPostBack) or not. Doesn't matter if the submitting control is a Button, LinkButton or Hyperlink. Request.Form["hdn"] is also null. I have restarted my computer just in case and still no joy. I am missing something really simple I am sure of it but I can't see what
This is the first page nothing in the code behind
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="WebApplication2.WebForm1" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:LinkButton runat="server" PostBackUrl="~/WebForm2.aspx">click</asp:LinkButton>
<asp:HiddenField runat="server" ID="hdn" Value="3" />
</div>
</form>
</body>
</html>
This is the second page
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm2.aspx.cs" Inherits="WebApplication2.WebForm2" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
</div>
</form>
</body>
</html>
Code behind
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebApplication2
{
public partial class WebForm2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string s = ((HiddenField)this.PreviousPage.FindControl("hdn")).Value;
}
}
}
On confirm.aspx use PreviousPage.FindControl instead :
HiddenField hdnFieldName = this.PreviousPage.FindControl("hdnConfirm") as HiddenField;
string hiddenValue = string.Empty;
if (hdnFieldName != null)
{
hiddenValue = hdnFieldName.Value;
}
Here is good example to get you started.
What's going on Here:
By default with VS 2013 and Asp.Net v4.5.1 , there is a feature FriendlyUrls which is enabled.
The FriendlyUrls feature does kind of Asp.Net routing , thus changing URLs from localhost/webform1.aspx to localhost/webfrom1
PostbackUrl property will not work in combination with Asp.Net Routing. When ASP.NET routing is in use the PreviousPage URL is the final routed URL. The runtime will check for a file represented by the Routed URL now, which will be webform1 and NOT webfrom1.aspx. Since there is NO such file as webform1, so it will always set the PreviousPage to null.
Possible Solutions:
So, now you know the issue at hand.
1.) Either don't use the Routing system of Asp.Net Friendly Urls , in this case, therefore try adding the <%# PreviousPageType VirtualPath="~/WebForm1.aspx"%> to webform2.aspx page and check.
2.) OR if you keep the FriendlyURLs and hence the Routing system, make changes in your code to read the Form values using some other alternatives.
I have an
<input type="button" id="Button1">
in my Master1.master masterpage. (that resides in a <div>).
I also have a content page Main.aspx.
I want to set the visibility of the button to true when I access the content page Main.aspx, for example, from another page. (I have a Login.aspx page, and after I insert user/psw and press a button I ged redirected to Main.aspx).
I have added the directive <%# MasterType virtualpath="~/Master1.master" %>
and i am using the following code
Button home = new Button();
home = (Button)Master.FindControl("Button1");
home.Visible = false;
However I get a NullReferenceException when i try to run this.
So basically I can't see the "Button1".
I have tried to change the values to head or ContentHolder1 and with these it runs perfectly.
Can anyone please help me ?
You can't access input which is not a server side control :
Youll need :
<input type="button" id="Button1" runat="server">
You need to add runat attribute:
<input type="button" id="Button1" runat="server">
Have the master page expose a property that you can then use to reference the Button. The ID of the control is going to be changed during the render event; that is why you cannot find it. Using the property on the master page, you can then address the control by accessing the Page.Master variable. You will need to cast it into the master page class so that you can use IntelliSense to access the public and friend methods/properties. Here is some code ... sorry it is in VB.
Here is the master page HTML.
<%# Master Language="VB" CodeFile="MasterPage.master.vb" Inherits="MasterPage" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<asp:ContentPlaceHolder id="head" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
<form id="form1" runat="server">
<div>
<input type="button" id="button1" runat="server" />
<asp:ContentPlaceHolder id="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
</div>
</form>
</body>
</html>
Here is the master page code-behind.
Partial Class MasterPage
Inherits System.Web.UI.MasterPage
Public ReadOnly Property Button As Control
Get
Return button1
End Get
End Property
End Class
Here is the content page.
Partial Class Default2
Inherits System.Web.UI.Page
Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
CType(Page.Master, MasterPage).Button.Text = "My Text"
End Sub
End Class
Notice the rendered control name below; they are not what you expect. You can get the real rendered name from the UniqueID property.
I know this is a very common problem. I was trying to get a "enter key" event to invoke a click on a certain button on the page through javascript. However, I can't for the life of me fetch a single element by its id or name from my asp.net page.
It is my understanding that this issue is related to where the javascript is located and whether the elements have been rendered by the time the javascript is loaded or something of that nature?
Every time I attempt to use var x = document.getElementById('btn_AddAdmin') I end up with a null value.
My asp.net page has SiteMaster page that it inherits from. I have included a trimmed down version of my asp.net page and the SiteMaster page.
ASP.NET Page:
<%# Page Title="" Language="C#" MasterPageFile="~/Site.Master"
AutoEventWireup="true" CodeBehind="Admin.aspx.cs" Inherits="HERMES.Admin" %>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<input type="text" id="txt_AddAdmin" runat="server" onkeypress="Populate()" />
Master Page:
<%# Master Language="C#" AutoEventWireup="true" CodeBehind="Site.master.cs"
Inherits="HERMES.SiteMaster" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head runat="server">
<title></title>
<link href="./Styles/Site.css" rel="stylesheet" type="text/css" />
<asp:ContentPlaceHolder ID="HeadContent" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
<form runat="server">
</form>
</body>
Sorry for the formatting, I seem to be doing something wrong...
I have attempted placing the javascript in many different locations -- anywhere from the sitemaster page to the top and bottom of my asp.net page. No luck either way.
var x = document.getElementById('<%= btn_AddAdmin.ClientID %>');
If your button is a Server Control it prepends a naming scheme to the input button so it can be bound back to the appropriate server control during postback. Thus the need to use the ClientID property to retrieve the "rendered id".
To learn more visit:
http://www.asp.net/web-forms/overview/client-script,-jquery,-and-ajax
http://www.asp.net/
Google it with Bing:
clientid
aspnet webforms client side programming
I am building a website which allows people to send out emails to people with a choice of different templates. When they have set-up their email and chosen a template the user can preview it. At present this loads up the corresponding aspx page to the template selected.
I currently have 3 templates but expect this to grow substantially.
The aspx pages all have the same controls, with the same names and even the codebehind(cs) page is the same. So it would be far simpler and efficient if i could somehow tie this pages together and minimise repetition, perhaps even just using one page but loading up the HTML corresponding to the selected template.
I cant think of an appropriate way to do this, or even work out if its possible. Ive probably got to the point where i cant think straight on the matter since its giving me such a headache.
So.....
Please please please give me some solutions or even just suggestions. ;-)
Thanks.
ADDITIONAL INFO
As an additional problem, i have to recreate the templates programatically when the emails are created and sent out to recipients as HTML emails. This is done via a different page and thus results in more duplication that id like to minimise.
create a Page class, let say, TemplateViewerPage
TemplateViewerPage.cs
using System;
using System.Web.UI;
public partial class TemplateViewerPage : Page
{
protected override void OnLoad(EventArgs e)
{
// load your properties
_subject = "test";
_messageBody = "body";
base.OnLoad(e);
}
// your property
private string _subject;
public string Subject
{
get { return _subject; }
set { _subject = value; }
}
private string _messageBody;
public string MessageBody
{
get { return _messageBody; }
set { _messageBody = value; }
}
}
then you can create viewer for template A :
ViewerA.aspx
<%# Page Language="C#" AutoEventWireup="false" Inherits="TemplateViewerPage" CodeFile="TemplateViewerPage.cs" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<table>
<tr>
<td>Subject</td>
<td> <%= Subject %> </td>
</tr>
<tr>
<td>Message</td>
<td> <%= MessageBody %> </td>
</tr>
</table>
</div>
</form>
</body>
</html>
and ViewerB, with same code behind (codefile=TemplateViewerPage.cs)
ViewerB.aspx:
<%# Page Language="C#" AutoEventWireup="false" Inherits="TemplateViewerPage" CodeFile="TemplateViewerPage.cs" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<div class="subject">
<%= Subject %>
</div>
<div class="message">
<%= MessageBody %> </td>
</div>
</div>
</form>
</body>
</html>
How about MasterPages for the templates? The select the appropriate master page at PageLoad.
If it's content then using CSS for the formatting (you can obviously change the CSS being loaded at Pageload) also Placeholders and populating them from your data store for the mails is another option.
It think there are probably as many solutions as there are users on StackOverflow ;)
If all the controls and code behind are the same, couldn't you put all the controls into a masterpage and simply use content pages for the actual emails?
Ah I see. Although it changes is it always in a similar structure? Because you can have multiple content holders in a masterpage. So in the masterpage you would be able to have content wrapped around the controls as follows:
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
<asp:Button ID="button1" runat="server" />
<asp:ContentPlaceHolder ID="ContentPlaceHolder2" runat="server">
</asp:ContentPlaceHolder>
I haven't found that the asp.net web forms page, master pages, or mvc is a very good fit for this sort of thing. It's like using a sledgehammer to crack open a peanut.
It's very straightforward to create some custom xml tags and then merge them yourself. Save the template in the database and merge whenever you like, and without all the overhead of running asp.net. Use agile principles: create your tests first and work backwards and you'll have exactly what you need running in no time.
The most basic is straight string replacement. If you need more, which it doesn't sound like you do, you could use xslt or just walk the DOM (ie store your templates as xhtml and have your own custom tag support).
There's also an issue of deployment. It's a lot easier to update templates in a database than it is to upload files to a server. If you do go down the route of using web forms, make sure you understand the deployment scenario's before you .
Warning: html emails are tricky, and there's a lot of ugliness (from an html standpoint) to get them to render uniformly in email clients. Expect to code the html like it's 1999, and that's pretty much the state of html emails. Sad but true.