user control code behind not executing

Topics: General, Troubleshooting
Jun 9, 2011 at 1:46 AM

I am trying to create a user control to gather user information and then send it out within an emial.  I was able to create the ascx page and i got it to display on the cms website but when I click on the send button all the text boxes get cleard out and no email is sent.  I test this same user control in another project and it works.

Not sure what I am missing.

At this point what I am trying acomplish is to be able to incorporte my own asp.net code and the ability to send out emails.

I even tried to set all the text boxes text to  "test" after submit and thats not ehappening either.

In my contact us page within the composite admin section this is the code I have:

<asp:form xmlns:asp="http://www.composite.net/ns/asp.net/controls">
        <f:function name="Composite.AspNet.LoadUserControl" xmlns:f="http://www.composite.net/ns/function/1.0">
          <f:param name="Path" value="~/Frontend/contactus.ascx" />
        </f:function>
      </asp:form>

 

this is the code in my User control: ( tried using asp:text boxes as well as you text box)

 

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="ContactUS.ascx.cs" Inherits="Composite_controls_FormsControls_ContactUS" %>
<style type="text/css">
    .style1
    {
        color: #FF0000;
    }
</style>
<p>&nbsp;
</p>
<p>
    First Name:<span class="style1"> *&nbsp;&nbsp;
    <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ControlToValidate="txtFirst"
        ErrorMessage="Required"></asp:RequiredFieldValidator>
    </span>
    <br />
    <aspui:TextBox ID="txtFirst" runat="server" Width="297px"></aspui:TextBox>
</p>
<p>
    Last Name:<span class="style1"> *&nbsp;&nbsp;
    <asp:RequiredFieldValidator ID="RequiredFieldValidator2" ControlToValidate="txtLast"
        runat="server" ErrorMessage="Required"></asp:RequiredFieldValidator>
    </span>
    <br />
    <aspui:TextBox ID="txtLast" runat="server" Width="297px"></aspui:TextBox>
</p>
<p>
    Company Name:<span class="style1"> *&nbsp;&nbsp;
    <asp:RequiredFieldValidator ID="RequiredFieldValidator3" ControlToValidate="txtCompany"
        runat="server" ErrorMessage="Required"></asp:RequiredFieldValidator>
    </span>
    <br />
    <aspui:TextBox ID="txtCompany" runat="server" Width="297px"></aspui:TextBox>
</p>
<p>
    Title:<br />
    <aspui:TextBox ID="txtTitle" runat="server" Width="297px"></aspui:TextBox>
</p>
<p>
    Phone Number:<span class="style1">*&nbsp;&nbsp;
    <asp:RequiredFieldValidator ID="RequiredFieldValidator4" ControlToValidate="txtPhone"
        runat="server" ErrorMessage="Required"></asp:RequiredFieldValidator>
    </span>
    <br />
    <aspui:TextBox ID="txtPhone" runat="server" Width="297px"></aspui:TextBox>
</p>
<p>
    Email:<span class="style1"> *&nbsp;&nbsp; </span><asp:RequiredFieldValidator ID="RequiredFieldValidator5" runat="server" ControlToValidate="txtEmail"
        ErrorMessage="Required"></asp:RequiredFieldValidator>
    <br />
    <aspui:TextBox ID="txtEmail" runat="server"
        Width="297px"></aspui:TextBox>
    <br />
    <asp:RegularExpressionValidator ID="RegularExpressionValidator1" runat="server" ControlToValidate="txtEmail" ValidationExpression="\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*"
        ErrorMessage="Invalid Email format"></asp:RegularExpressionValidator>
</p>
<p>
    Comments:<br />
    <aspui:TextBox ID="txtComments" runat="server" Height="194px"
        TextMode="MultiLine" Width="371px"></aspui:TextBox>
</p>
<p>&nbsp;</p>
<p>
    <asp:Button ID="btnSubmit" runat="server" Text="Send"
        onclick="btnSubmit_Click" />
   </p>

 


this is the code behind the user control:

 


using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Composite.C1Console.Forms;
using Composite.Plugins.Forms.WebChannel.UiControlFactories;

public partial class Composite_controls_FormsControls_ContactUS : UserControlBasedUiControl
{
    protected void Page_Load(object sender, EventArgs e)
    {
    }

    public override void InitializeViewState()
    {
    }

    public override void BindStateToControlProperties()
    {
    }

   
    protected void btnSubmit_Click(object sender, EventArgs e)
    {
        string msgBody;
        System.Net.Mail.MailMessage message = new System.Net.Mail.MailMessage();
        message.From = new System.Net.Mail.MailAddress(RemoveEscape(txtEmail.Text.Trim()));
        message.To.Add(ConfigurationManager.AppSettings.Get("AboutToEmail").ToString());
        message.Subject = "WISC - Contact US";
        message.IsBodyHtml = true; // .BodyFormat = MailFormat.Html;
        msgBody = "<html><body><table><tr><td>First Name:</td>";
        msgBody += "<td>" + RemoveEscape(txtFirst.Text.Trim()) + "</td>";
        msgBody += "</tr><tr><td>Last Name:</td>";
        msgBody += "<td>" + RemoveEscape(txtLast.Text.Trim()) + "</td>";
        msgBody += "</tr><tr><td>Company:</td>";
        msgBody += "<td>" + RemoveEscape(txtCompany.Text.Trim()) + "</td>";
        msgBody += "</tr><tr><td>Title:</td>";
        msgBody += "<td>" + RemoveEscape(txtTitle.Text.Trim()) + "</td>";
        msgBody += "</tr><tr><td>Phone Number:</td>";
        msgBody += "<td>" + RemoveEscape(txtPhone.Text.Trim()) + "</td>";
        msgBody += "</tr><tr><td>email:</td>";
        msgBody += "<td>" + RemoveEscape(txtEmail.Text.Trim()) + "</td>";
        msgBody += "</tr><tr><td>Comments:</td>";
        msgBody += "<td>" + RemoveEscape(txtComments.Text.Trim()) + "</td>";
        msgBody += "</tr></table></body></html>";

        message.Body = msgBody;

        System.Net.Mail.SmtpClient smtp = new System.Net.Mail.SmtpClient();
        //smtp.Host = ConfigurationManager.AppSettings.Get("MailServer").ToString();
        //smtp.Host = "mail server";
        //smtp.Credentials = new System.Net.NetworkCredential("username", "password");
        smtp.Send(message);

        Response.Write(@"<script language='javascript'>alert('Your request has been sent.');</script>");
        txtEmail.Text = "test";
        txtComments.Text = "test";
        txtCompany.Text = "test";
        txtFirst.Text = "test";
        txtLast.Text = "test";
        txtPhone.Text = "test";
        txtTitle.Text = "test";

    }

    public static string RemoveEscape(string input)
    {
        input = input.Replace("'", "''");
        input = input.Replace("\"", "");
        input = input.Replace(")", "");
        input = input.Replace("(", "");
        input = input.Replace(";", "");
        input = input.Replace("-", "");
        input = input.Replace("|", "");

        return input;
    }

    public static string ReplaceBadChar(string input)
    {

        input = input.Replace("<", "&lt;");
        input = input.Replace(">", "&gt;");
        input = input.Replace("'", "&apos;");
        input = input.Replace("\"", "&#22;");
        input = input.Replace(")", "&#x29;");
        input = input.Replace("(", "&#x28;");

        input = RemoveEscape(input);

        return input;
    }

}

Jun 10, 2011 at 9:06 AM

have you tried to insert a throw new Exception("hey"); in the very top of your btnSubmit_Click method to test if it gets called at all?

Jun 13, 2011 at 11:32 AM

it's not, as you can see in my code I set all the text boxes text to "test" on the btnsubmit_click and its not doing it.  I as soon as you click the submit button all the values of the text boxes are cleard out and the code behind is not executed. thanks in advance.

txtEmail.Text = "test";
txtComments.Text = "test";
txtCompany.Text = "test";
txtFirst.Text = "test";
txtLast.Text = "test";
txtPhone.Text = "test";
txtTitle.Text = "test";

Jun 14, 2011 at 7:21 AM

Try moving your server-side form into your usercontrol, instead of letting C1 handling it.

So the C1 function looks like this instead

<f:function name="Composite.AspNet.LoadUserControl" xmlns:f="http://www.composite.net/ns/function/1.0">
  <f:param name="Path" value="~/Frontend/contactus.ascx" />
</f:function>

and your usercontrol is

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="ContactUS.ascx.cs" Inherits="Composite_controls_FormsControls_ContactUS" %>
<style type="text/css">
    .style1
    {
        color: #FF0000;
    }
</style>

<form runat="server">
<p>&nbsp;
</p>
<p>
    First Name:<span class="style1"> *&nbsp;&nbsp; 
    <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ControlToValidate="txtFirst"
        ErrorMessage="Required"></asp:RequiredFieldValidator>
    </span>
    <br />
    <aspui:TextBox ID="txtFirst" runat="server" Width="297px"></aspui:TextBox>
</p>

 ...

</form>

Coordinator
Jun 14, 2011 at 7:58 AM
Edited Jun 14, 2011 at 7:58 AM

Helo, iteron

I just tested your example and it works for me (Composite C1 2.1.1  Build no. 2.1.4113.99, XSLT and HTML based templates)

Seems to be I reproduced this problem on Master based site. Do you also use Master based site?

Jun 14, 2011 at 9:25 AM

I hope not... it would not make much sense to include a usercontrol like that on a Masterpage. There you would do it the normal asp.net way like this

<%@ Register TagPrefix="yay" TagName="contact" Src="Frontend/contactus.ascx" %>

<form runat="server">
   <yay:contact runat="server" />
</form>

Coordinator
Jun 14, 2011 at 9:45 AM
burningice wrote:

I hope not... it would not make much sense to include a usercontrol like that on a Masterpage. There you would do it the normal asp.net way like this

 

<%@ Register TagPrefix="yay" TagName="contact" Src="Frontend/contactus.ascx" %>

<form runat="server">
   <yay:contact runat="server" />
</form>

 

UserControl included directly on MasterPage works, but UserControl loaded from C1 page by using Composite.AspNet.LoadUserControl doesn't work on Master based site.

Currently don't know what is the problem, but it is a bug, and need to investigate dipper.

Jun 14, 2011 at 9:53 AM
Edited Jun 14, 2011 at 9:53 AM

Doesn't it work at all to insert a usercontrol, or is it just this postback scenario that is failing? What i'm doing in the C1MarkupControl which is what the Placeholder control inherits from, is to call PageRenderer.ExecuteEmbeddedFunctions(doc, FunctionContext); where doc is the content containing the C1 Load Usercontrol function, and thereafter call AsAspNetControl on the result and inserting it into the control tree. Just as the default implementation.

Only issue i can see here, is that this is all done in the CreateChildControls function called by the asp.net framework, which could be too late regarding firing postback events. I'll look into that.

Coordinator
Jun 14, 2011 at 9:57 AM
burningice wrote:

Doesn't it work at all to insert a usercontrol, or is it just this postback scenario that is failing?

Control is loaded, just Postback events don't work.

Jun 14, 2011 at 10:00 AM
Inna wrote:

Control is loaded, just Postback events don't work.

okay, so its safe to assume the issue lays in the timing of when the usercontrol is inserted to the control tree!

Jun 26, 2011 at 10:38 AM

Hi,

today I ran exactly in this problem... tried to load a User Control (E-Mail Form) on the page source with the Composite.AspNet.LoadUserControl function and nothing happens... I use MasterPages. Tried to solve it, but no success:

1. put <asp:form ... in the page source, surrounding the <f:function name="Composite.AspNet.LoadUserControl" ...
  -> Postback after submit seems to happen, but no code behind is executed

2. put <form runat="server" id="myForm"> directly in ascx-Code
  ->
Postback after submit seems to happen, but no code behind is executed

3. put <form runat="server" id="myForm"> in the MasterPage Markup, directly after <body>, surounding all other body markup
  -> nothing happens, no postback, no code behind
  -> additionally my page layout misbehaves:
I have a header div with a background image. When putting the <form runat="server" id="myForm"> on my MasterPage, it duplicates somehow, look here: http://www.mmds.de/temp/postings/formproblem.jpg

Unfortunatley #3 would be the best approach to insert a form-Tag in the Markup, but it's the one that causes the most problems :-(

Is there already a bugfix? At the Moment I simply do not know how to implement my e-mail contact form, unless discarding the master page layout (which is not an option)!

 

Thanx, Stephan

Jun 27, 2011 at 8:26 AM
Edited Jun 27, 2011 at 8:27 AM

steschu,

are you able to compile the source for Contrib yourself? In the class C1MarkupControl you should add the following method

protected override OnInit(EventArgs e)
{
   if (Page.IsPostBack && !ChildControlsCreated)
   {
      base.CreateChildControls();
   }

   base.OnInit(e);
}
compile and try to see of that fixes it.
Jun 27, 2011 at 3:27 PM

bug confirmed, reproduced, fixed, fix was reproduced and changes is comitted, including binaries and package

http://compositec1contrib.codeplex.com/SourceControl/changeset/changes/68173

Jun 29, 2011 at 8:47 AM

burningice,
Thank you for fixing this bug!

We updated Contribution.CompositeC1Contrib.Core with new dll and starter package based on master pages. 

Jun 29, 2011 at 11:48 AM
Edited Jun 29, 2011 at 11:52 AM

Hi all,

Thanx for help. I tried every of my 3 variants (see posting above). Here is the result:

1. using <asp:form ... in page source: works fine!

2. using <form runat="server" ... in ascx-Markup: works fine!

3. using <form runat="server" ... in MasterPage: Different behaviour in different browsers, unfortunately almost nowhere working fine (except Safari):
For debugging reasons I put a Button and a Label control on my master page. And in the Button_OnClick-EventHandler in the code behind: Label1.Text = "Hello World";

Here is what happens, after clicking the button:

IE9 IE9 comp. mode(=IE8?) FF5 Safari 4 Opera 11

Layout: doubled header div

Postback: nothing happens

Layout: no doubled header div,
slight differences, but tolerable

Postback: nothing happens

Layout: ok

Postback: see error below in red

 Layout: ok

Postback: works as it should,
"Hello World" is displayed!!!

Layout: ok

Postback: nothing happens

Firefox error: Invalid postback or callback argument.  Event validation is enabled using <pages enableEventValidation="true"/> in configuration or <%@ Page EnableEventValidation="true" %> in a page.  For security purposes, this feature verifies that arguments to postback or callback events originate from the server control that originally rendered them.  If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation method in order to register the postback or callback data for validation.

I tried the following: Added the <pages enabledEventValidation="false/true" /> to the web.config This doesn't work either. Same error.

So, good news is: I could use my mail form with a form tag in the ascx-markup or in page code.

Bad news: I cannot use one global form in my master page, as it would be normal in asp .NET programming. If I would like to have several postback buttons on my master page I had to realize each of it with a seperate usercontrol using its own form tags ... but then, the whole asp .NET thing doesn't work anymore, does it? A certain form only contains postback Informations of controls inside the form. If I am to access a property of a control that lays outside the form, in which the postback control is, the property value wouldn't be available?

Stephan

Jun 29, 2011 at 12:01 PM

Sorry, here is an update to my last posting! It seems that the described error with the master pages comes from using the SimpleSearch function, which I use in my master page:

<rendering:Function ID="fnSiteSearch" runat="server">
  <f:function name="Composite.Search.SimplePageSearch.SearchForm" xmlns:f="http://www.composite.net/ns/function/1.0">
    <f:param name="SearchButtonLabel" value="" />"
    <f:param name="SearchResultPage" value="ec4d8945-4dad-4a74-ad8e-651616b7bb78" />
  </f:function>
</rendering:Function>

Since that function renders another form tag, and my global form tag wrapps that search form tag, the error occurs. If I delete the Simple Search function from my master pages everything works fine.

Any idea how I could use the SimpleSearch instead - without resulting in a "form tag collision"?

Cheers, Stephan

Jun 29, 2011 at 12:24 PM

Looking at the source quickly shows that SimplePageSearch is rendering its own simple form http://c1packages.codeplex.com/SourceControl/changeset/view/8053#129515. As you have found out the hard way this causes problems if you're at the same time decorating your whole page with a <form> since you can't nest forms. You can have several forms on one page, but not nest them.

I don't know how or where on your page you insert the search function, but can't you maybe put it in some Toolbar on the top of the page and then only wrap the content-area of your page in a global server form?

Like you see it here on Codeplex, where the search box is in the top right corner.

Jun 29, 2011 at 4:41 PM
Edited Jun 29, 2011 at 4:42 PM

Hi Burningice,

Yes, after your bugfix I totally lost sight of the search form...

You're right, I could put the "global" form after the search form. But I think, that's only a trade off and there might be cases where you cannot solve it like this.

A better way is to abandon the Composite C1 SimpleSearch function call on the master page and implement the functionality with asp .NET means. In this case, all you have to do is creating a URL redirect with the search Textbox input.

In ASPX-Markup:

<span class="searchLabel">Search:</span><asp:TextBox ID="TextBoxSearch" runat="server" MaxLength="1000"></asp:TextBox><asp:Button ID="ButtonSearch" runat="server" Text="" CssClass="searchButton" OnClick="ButtonSearch_Click" />

In Code Behind:

    protected void ButtonSearch_Click(object sender, EventArgs e)
    {
        string searchText = TextBoxSearch.Text.Trim();

        if (!String.IsNullOrEmpty(searchText))
            Response.Redirect(String.Format("~/Home/Search.aspx?SearchQuery={0}", System.Web.HttpUtility.UrlEncode(searchText)));
    }

Or even better: Encapsulate the logic in a user control!

Search.aspx will just work fine with the normal Xslt/Composite.Search.SimplePageSearchSerachResults/SearchResults.xsl function (but you should delete the part with the search input on the result page). Or you probably can implement a SearchResult Control on your own, using the Composite.Search.SimplePageSearch.Function class?

I would find it usefull, if there could be a note here (http://docs.composite.net/C1/ASP-NET/Form.aspx) or somewhere in the CompsoiteC1Contrib project that .NET develops using master pages should be aware of Contrib C1 packages that render a form tag on their own! As seen it could lead to a nested form problem.

Steschu

P.S.: The UrlFilter does not work with the Search

Jun 29, 2011 at 8:54 PM
Edited Jun 29, 2011 at 8:57 PM

Im not myself a lover of the whole "having one form that wraps it all" approach in WebForms because of exactly situations like these. It has nothing to do with C1 or masterpages though, its a general Webforms issue. The correct solution by Composite would be not to let the Search function render its own Form but let it be handled by the user who is dropping it in their template or on the page. Optionally there should be an argument specifying whether you want it to render a <form> tag or not. This way you can easily change the method from get to post and specify a custom url as landing page if you wanted.

This should be posted as a feature request to the Composite team though.

PS. what is not working with the UrlFilter? Error, stacktrace or did it just eat your dog? :)

Jun 30, 2011 at 7:16 AM
Edited Jun 30, 2011 at 7:16 AM

> what is not working with the UrlFilter? Error, stacktrace or did it just eat your dog? :)

Ah, you need some error description - thought that "not working" was detailed enough ;-)

The Url of the search page is not resolved, it remains in the "normal" Composite c1 form:
http://[Domain]/Home/Search.aspx?SearchQuery=xyz

Maybe because a QueryString Parameter is used?

Steschu

Jun 30, 2011 at 7:43 AM

What happens if you write it out with asp.net instead?

throw new Exception(Request.QueryString["SearchQuery"])

Jun 30, 2011 at 7:58 AM
Edited Jun 30, 2011 at 8:01 AM

Fixed it, you already have to use the resolved url in the function (either the .NET redirect or the normal SimplePageSearch) and it works.

e.g.: Response.Redirect(String.Format("~/Search?SearchQuery={0}", System.Web.HttpUtility.UrlEncode(searchText)));

Thanx + Have nice day.

Stephan

Jun 30, 2011 at 8:06 AM
Edited Jun 30, 2011 at 8:07 AM

Ah yeah... if you don't wan't to hardcode the path but wan't to specify a guid instead you can use this

var path = SiteMap.Provider.FindSiteMapNodeByKey("your guid as string").Url;

The C1 url format with extension and homepage-name will only get converted to NicerUrl when its present as links in your content