Forms with PageTypeBuilder

Vote:
 

Hi everyone

I'm using the PageTypeBuilder to create pages but now I need to be able to create forms. The AlloyTech template uses a Form template to do so, but I can't seem to replicate the code because I am using the PageTypeBuilder. Is there anyway I could still get the same functionality that the Form template offers?

Thanks in advance.

#53449
Sep 08, 2011 23:35
Vote:
 
#53450
Sep 09, 2011 6:55
Vote:
 

You can use the XForms stuff from AlloyTech templates. To use it together with PTB you can do something like this:

[PageTypeProperty(Type = typeof(PropertyXForm))]
public virtual XForm XForms
{ 
    get
    {
        return  ((PropertyXForm) 
            this.Property[this.GetPropertyName(
                page => page.XForms)]).Form;
    } 
}

Hope this helps.

Frederik  

#53460
Sep 09, 2011 9:00
Vote:
 

Thank you, that was exactly what I was looking for! Great tutorial Frederik!

I am, however, encoutering several problems :s

- When I create a basic form, I can't submit the form itself, the button doesn't respond, IE tells me "WebForm_PostBackOptions" is undefined... Google offers me a lot of solutions but none of them seem to do the trick :s

- When I create a form with validation, I get the error "Control ...FormControl_Namerequirevalidator" of type 'RequiredFieldValidator' must be placed inside a form tag with runat="server"

Any suggestions on how to fix this would be appreciated.

#53464
Sep 09, 2011 10:11
Vote:
 

Make sure the form is located inside a form element with the runat="server" attribute.

Frederik

#53465
Sep 09, 2011 10:28
Vote:
 

Yes, that did the trick! Well, it wasn't in the tutorial so I didn't think about it, I did try with a div but that wasn't good enough :P

Thanks for the replies and for the great tutorial!

#53466
Sep 09, 2011 10:52
Vote:
 

No problem. Glad it was useful :).

#53468
Sep 09, 2011 10:55
Vote:
 

I got some extra questions, the option to send the user to a specific page after the form was sent doesn't seem to work, any clues?

 

#53470
Sep 09, 2011 11:20
Vote:
 

You need to attach a little code to a few of XForms events AfterSubmitPostedData etc. The code can be found in AlloyTech sample site in Global.asax.cs.

using System;
using System.Linq;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;
using EPiServer.Core;
using EPiServer.Globalization;
using EPiServer.Web;
using EPiServer.XForms.WebControls;
using Label = System.Web.UI.WebControls.Label;

namespace EPiServer.Templates
{
	public class Global : EPiServer.Global
	{
		protected void Application_Start(Object sender, EventArgs e)
		{
            XFormControl.ControlSetup += new EventHandler(XForm_ControlSetup);
        }

        #region Global XForm Events

        /// <summary>
        /// Sets up events for each new instance of the XFormControl control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        /// <remarks>As the ControlSetup event is triggered for each instance of the XFormControl control
        /// you need to take into consideration that any event handlers will affect all XForms for the entire
        /// application. If the EPiServer UI is running in the same application this might also be affected depending
        /// on which events you attach to and what is done in the event handlers.</remarks>
        public void XForm_ControlSetup(object sender, EventArgs e)
        {
            XFormControl control = (XFormControl)sender;

            control.BeforeLoadingForm += new LoadFormEventHandler(XForm_BeforeLoadingForm);
            control.ControlsCreated += new EventHandler(XForm_ControlsCreated);
            control.BeforeSubmitPostedData += new SaveFormDataEventHandler(XForm_BeforeSubmitPostedData);
            control.AfterSubmitPostedData += new SaveFormDataEventHandler(XForm_AfterSubmitPostedData);
        }

        /// <summary>
        /// Handles the BeforeLoadingForm event of the XFormControl.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EPiServer.XForms.WebControls.LoadFormEventArgs"/> instance containing the event data.</param>
        public void XForm_BeforeLoadingForm(object sender, LoadFormEventArgs e)
        {
            XFormControl formControl = (XFormControl)sender;
            
            if (String.IsNullOrEmpty(formControl.ValidationGroup))
            {
                //We set the validation group of the form to match our global validation group in the master page if no group has been defined.
                formControl.ValidationGroup = "XForm";
            }
        }

        /// <summary>
        /// Handles the ControlsCreated event of the XFormControl.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        public void XForm_ControlsCreated(object sender, EventArgs e)
        {
            XFormControl formControl = (XFormControl)sender;

            //We set the inline error validation text to "*" as we use a
            //validation summary in the master page to display the detailed error message.
            foreach (BaseValidator validator in formControl.Controls.Cast<Control>().Where(ctrl => ctrl is BaseValidator))
            {
                validator.Text = "*";
            }
            
            if (formControl.Page.User.Identity.IsAuthenticated)
            {
                formControl.Data.UserName = formControl.Page.User.Identity.Name;
            }
        }

        /// <summary>
        /// Handles the BeforeSubmitPostedData event of the XFormControl.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EPiServer.XForms.WebControls.SaveFormDataEventArgs"/> instance containing the event data.</param>
        public void XForm_BeforeSubmitPostedData(object sender, SaveFormDataEventArgs e)
        {
            XFormControl control = (XFormControl)sender;

            PageBase currentPage = control.Page as PageBase;

            if (currentPage == null)
            {
                return;
            }

            //We set the current page that the form has been posted from
            //This might differ from the actual page that the form property exists on.
            e.FormData.PageGuid = currentPage.CurrentPage.PageGuid;
        }

        /// <summary>
        /// Handles the AfterSubmitPostedData event of the XFormControl.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EPiServer.XForms.WebControls.SaveFormDataEventArgs"/> instance containing the event data.</param>
        public void XForm_AfterSubmitPostedData(object sender, SaveFormDataEventArgs e)
        {
            XFormControl control = (XFormControl)sender;

            if (control.FormDefinition.PageGuidAfterPost != Guid.Empty)
            {
                PermanentPageLinkMap pageMap = PermanentLinkMapStore.Find(control.FormDefinition.PageGuidAfterPost) as PermanentPageLinkMap;
                if (pageMap != null)
                {
                    string internalUrl = pageMap.MappedUrl.ToString();
                    internalUrl = UriSupport.AddLanguageSelection(internalUrl, ContentLanguage.PreferredCulture.Name);
                    UrlBuilder urlBuilder = new UrlBuilder(internalUrl);
                    //Rewrite the url to make sure that it gets the friendly url if such a provider has been configured.
                    Global.UrlRewriteProvider.ConvertToExternal(urlBuilder, null, Encoding.UTF8);

                    //Always cast UrlBuilders to get a correctly encoded url since ToString() is for "human" readability.
                    control.Page.Response.Redirect((string)urlBuilder);
                    return;
                }
            }

            //After the form has been posted we remove the form elements and add a "thank you message".
            control.Controls.Clear();
            Label label = new Label();
            label.CssClass = "thankyoumessage";
            label.Text = LanguageManager.Instance.Translate("/form/postedmessage");
            control.Controls.Add(label);
        }

        #endregion

        protected void Application_End(Object sender, EventArgs e)
		{
		}

        /// <summary>
        /// Raises the <see cref="E:ValidateUIAccess"/> event. Override this in inheriting classes to customize behavior,
        /// always calling the base-class implementation as well. Check for e.Cancel == true and do an early exit if so.
        /// </summary>
        /// <remarks>
        /// This is only a code sample on how you can utilize this event.
        /// </remarks>
        /// <param name="e">The <see cref="EPiServer.ValidateUIAccessEventArgs"/> instance containing the event data.</param>
        protected override void OnValidateRequestAccess(ValidateRequestAccessEventArgs e)
        {
            base.OnValidateRequestAccess(e);
            if (e.Cancel)
            {
                return;
            }
        }

        /// <summary>
        /// Gets a list of default documents. Overide if you need to change which documents are actually
        /// tried.
        /// </summary>
        /// <remarks>
        /// This is only a code sample on how you can utilize this method.
        /// </remarks>
        /// <param name="url">The URL of the request that is determined to need a default document</param>
        /// <returns>null or a list of default documents to try</returns>
        protected override string[] GetDefaultDocuments(Uri url)
        {
            return base.GetDefaultDocuments(url);
        }
    }
}

    

#53472
Sep 09, 2011 11:22
Vote:
 

Nope, still nothing :( The form itself is submitted because I can see the data in Form Data but the redirect just doesn't work. Maybe I'm probably overseeing something in the global file... but it builds without errors so I'm stuck again :(

#53476
Sep 09, 2011 11:45
Vote:
 

The redirect happens on line 110 and down. Could you set a breakpoint there and debug?

#53477
Sep 09, 2011 11:47
Vote:
 

Well that's another issue I've been having :s When I start debugging in VS, the localhost page opens but only shows an error "Object reference not set to an instance of an object"...

#53478
Sep 09, 2011 11:51
Vote:
 

What does the URL look like when you're debugging? Might be that you're trying to access the .aspx directly. Try instead hitting F5 (debug) and then pasting in the URL to the page that contains the form in your browsers address bar.

#53479
Sep 09, 2011 11:57
Vote:
 

The url looks like this "http://localhost:number/", I tried "http://localhost:number/Default.aspx" as well but that gives an error as well (The resource cannot be found). Could this be because of my setup? I currently do not have an internet connection on that machine, but more importantely there is a SharePoint website running as intranet, could this have anything to do with it?

#53480
Sep 09, 2011 12:06
Vote:
 

I think you need to have an active network connection at least. When you browse your site normally what does the URL look like?

#53481
Sep 09, 2011 12:11
Vote:
 

I can't "View in Browser" neither, same error

#53482
Sep 09, 2011 12:15
Vote:
 

No, I mean browsing the site normally, like you would to get to admin/edit mode.

#53483
Sep 09, 2011 12:18
Vote:
 

Ah ok, that would be "http://pcname:number/" and for admin the name of the site behind it

#53484
Sep 09, 2011 12:25
Vote:
 

I figured it out. I copied the code form the global.asax file but somewhere there was an ambiguous type which was causing problems. It's fixed now, so thank you for your help!

#53503
Sep 12, 2011 10:37
This thread is locked and should be used for reference only. Please use the Episerver CMS 7 and earlier versions forum to open new discussions.