My wife Susie recently started a new membership organization called the National Association of Pet Rescue Professionals (NAPRP). The idea behind NAPRP is to make resources available to shelters and other animal rescue organizations so they can save the lives of more animals.

Members gain access to resources and meet each other virtually through the member web site (www.naprp.com), which we developed with DotNetNuke (DNN). DNN may not be the greatest platform for developing a membership site, but it has proven to be a decent starting point for our new organization. Despite various installation and configuration challenges, using it saved me from a whole lot of ASP.NET development work.

AWeber vs. DotNetNuke

The biggest problem we ran into was giving our members a way to subscribe to the NAPRP newsletter. We use AWeber to manage the subscriptions and to send an auto-responder: 101 Fundraising Ideas for Rescues, Shelters, and Humane Organizations.

AWeber conveniently gives you a chunk of HTML to insert into your page. Susie initially attempted to insert that chunk into a text/html module. That didn't work because you are effectively creating a form within a form. All DNN pages, like all normal ASPX pages, are wrapped with a surrounding FORM tag that is essential to their operation. You can't just yank the form tag out of the AWeber code either, because then you are creating a bunch of INPUT tags that are not "sited" on the page (i.e. they aren't hooked to an event handler). Even if you did post back the form, the underlying page would have no idea what to do with it.

Form Master to the Rescue -- Almost

We figured that we weren't alone with having this problem so Susie did some research into the issue on the DNN forum and the AWeber site. One proposed solution was to use the Form Master module by Code 5 Systems. This is a $50 module that lets you create forms within a DNN page. One of its features is that it can do a "silent post," which means you can give it a URL and it will generate a post for you upon submit.

The silent post option sounded good, so we ran with it. It worked, too, but only for a while. We recently heard from a subscriber who wondered why she never got her confirmation email. AWeber uses a double-opt in system that requires subscribers to verify their email address by clicking a link in a confirmation message. It turns out that, for about the past month, our subscribers have not been getting their confirmation messages, which is why we have had no subscribes. We just thought no one was subscribing yet because the site was so new.

Server-Side Posting Forbidden

We contacted AWeber technical support to find out why the form was working and then stopped working. Eventually, the dirty secret was revealed: AWeber limits how many subscribe requests can come from a specific IP address. Presumably, this is to prevent DOS attacks and mass automated subscribes.

Form Master failed us in this situation because the silent post operation takes place on the server. The server, not the client, is posting the form, so AWeber sees the same IP address over and over. Eventually they stopped accepting the requests. Unfortunately, AWeber does not give the list owner or the subscriber an indication that this has happened, which is why we remained ignorant for so long. The subscriber gets redirected to the thank you page as if everything went fine.

Of course, you would think that our subscribers would eventually notice that they did not get their confirmation email and that they weren't getting the auto-responder. And so someone eventually did...the day before we were supposed to launch.

Disappointing HTML Solution

With no time to spare, we had to come up with a solution fast. We knew that the subscribe form would work fine if we put it on a plain HTML Web page, so that's what we did for the short term. We linked to the HTML page from the membership site and linked back into the site from the HTML page. It was a real hack, but it worked.

The next morning, the hacked solution was really eating at my soul. Now that I knew the full nature of the problem, I figured there just had to be a way to get around it. I put on my Determined Programmer hat and started digging into DNN internals, ASP.NET internals, and page navigation issues. Everyone, including the dogs, knows to stay out of my hair while I'm working a problem like this.

Rolling Up My Sleeves

What I needed to do was conceptually very simple: I had to submit the subscriber form input fields to the AWeber URL, but I had to do it from the client, not the server.

My first step was to create a testing sandbox so I could isolate as many variables as possible. I started with a dead simple ASP.NET page with the AWeber form inside it. Rather than post to the AWeber site, I created a page that did nothing but dump the contents of Request.Form so I could see what was getting passed from my test page. Armed with these tools, I started tweaking.

Cross-Page Posting in DNN

The first problem to overcome was getting the form to post to the right target page. I needed a way to override the "action" of the page's form tag.

ASP.NET 2.0 introduced the PostBackUrl property on the Button control that lets you do this. Microsoft calls it a cross-page post. I knew it would work fine in my test project, but it would fail in DNN because you can't use ASP.NET server controls within a text/HTML module. There's no server code to emit the corresponding HTML tag.

The next best thing was to go ahead and put a button form into my test project, and then do a view source on the resulting HTML page to see how the control was rendered. It turns out that the button gets rendered as a submit input tag. The tag uses the __doPostbackWithOptions function to submit the form. Now I was getting somewhere.

I put the submit input tag into the DNN site and tried it out. The cross-page post seemed to work fine, but the target page got an empty Form collection. That problem made sense when I looked at the raw http headers and discovered that the DNN form is encoded as multipart/form-data, which packages your form variables along with any files you may be uploading through your Web page. The page receiving the post has to be expecting this encoding in order to handle it properly. In the old days of classic ASP, you needed a "posting acceptor" component to disassemble the data. I know because I wrote one in VB6 several years ago.

Form Encoding Override

First, I verified that AWeber would not accept multipart/form-data, and that turned out to be the case. So, back to the drawing board, as they say.

I finally decided that the built-in ASP.NET submit methods were just not going to do the trick for me. I needed to override not only the form action, but also the encoding, and __doPostbackWithOptions doesn't let you do the latter. In the end, I created my own function and popped it into the DNN text/HTML module just above my AWeber form:

<script type="text/javascript">
/* <![CDATA[ */
function __doExternalPost(targetUrl) {
   theForm.encoding = "application/x-www-form-urlencoded";
   theForm.action = targetUrl;
   theForm.submit();
}
/* ]]> */
</script>

The function first changes the form encoding back to the ASP.NET default of "application/x-www-form-urlencoded." It then overrides the form action to use the passed target URL. Finally, it submits the form. In case you are wondering, the "theForm" object is initialized by standard ASP.NET JavaScript early in the page. If you do a View Source on any ASP.NET page, you'll see the initialization code in a SCRIPT tag that also defines the __doPostBack function.

I changed the input tag to use my new function:

<input type="submit" name="btnSubmit" value="Subscribe"
onclick="javascript:__doExternalPost(&quot; http://www.aweber.com/scripts/addlead.pl&quot;);"
  id="btnSubmit" />

I discovered that I could also use an anchor tag (i.e. a rendered Hyperlink or LinkButton control):

<a id="newsletterSubscribe" title="Subscribe" class="CommandButton"
href="javascript:__doExternalPost(&quot;http://www.aweber.com/scripts/addlead.pl&quot;);">
Subscribe</a>

Success at last! Our subscribe submissions now get to AWeber successfully.

A Few Final Tweaks

Of course, when you post the form, you pass more than just the AWeber form fields. You also pass every other field in the ASP.NET form. Susie didn't like the extra junk being passed through on her notification emails, so I cleared VIEWSTATE, the largest offender (__dnnVariable is another candidate). The updated __doExternalPost looks like this:

<script type="text/javascript">
/* <![CDATA[ */
function __doExternalPost(targetUrl) {
   theForm.__VIEWSTATE.value = "";
   theForm.encoding = "application/x-www-form-urlencoded";
   theForm.action = targetUrl;
   theForm.submit();
}
/* ]]> */
</script>

Here's what the full AWeber form code finally looked like:

<input type="hidden" name="meta_web_form_id" value="1234567890">
<input type="hidden" name="meta_split_id" value="">
<input type="hidden" name="unit" value="naprp">
<input type="hidden" name="redirect" value="http://www.naprp.com/Thankyou/tabid/55/Default.aspx">
<input type="hidden" name="meta_redirect_onlist" value="">
<input type="hidden" name="meta_adtracking" value="">
<input type="hidden" name="meta_message" value="1">
<input type="hidden" name="meta_required" value="from">
<input type="hidden" name="meta_forward_vars" value="0">
<table>
<tr>
  <td class="Normal"><b>* Email</b></td>
  <td><input type="text" name="from" value="" size="30"></td>
</tr>
<tr>
  <td class="Normal"><b>* Name</b></td>
  <td><input type="text" name="name" value="" size="30"></td>
</tr>
<tr>
  <td align="center" colspan="2">
    <a id="newsletterSubscribe" title="Subscribe" class="CommandButton"
      href="javascript:__doExternalPost(&quot;http://www.aweber.com/scripts/addlead.pl&quot;);">
      Subscribe</a></td>
</tr>
</table>

A Solution for ASP.NET Cross-Site Posting

Although I needed my __doExternalPost function to solve the AWeber problem, you could use the same technique for any situation where you needed to post information from a DotNetNuke page to an off-site page. For example, you could use the same technique for PayPal buttons.

Free AWeber to DotNetNuke Conversion Tool!

After reading a number of postings on the Web related to this topic, I realized that a lot of people who have this problem are not really programmers. They don't feel comfortable messing around with JavaScript in their pages. So, I put together a little conversion utility that tweaks the AWeber form code for you. Just be sure that you take the code exactly as AWeber generates it:

AWeber to DotNetNuke Conversion Utility

Happy coding!

Visitor Comments

To submit your comments, click the "Please click here to send feedback" link below.

Hi there,

Just wanted to send you a big Thank You for the Aweber conversion utility! Your fix has saved me a lot of time, and I've been struggling with this issue for a while. I'm actually using a different CMS called My Web Pages Starter Kit, and your fix works perfectly with it, as well.

FYI - one item I noticed on the script builder was that my customized thank you url reverted back to the default aweber url when I ran the converter. Other than that, no problems.

Also, I posted a link to your site on the MWPSK dev. board: http://www.codeplex.com/MyWebPagesStarterKit/Thread/View.aspx?ThreadId=21583

Thanks again!

-- Adam

Adam:

Thanks for taking the time to send feedback. I'm glad the AWeber conversion utility was useful to you. I hadn't really thought about it, but it makes sense that the technique would work in any .NET-based CMS.

I'm not sure what happened with your thank you URL. The script converter does only two things: it removes the FORM tag, and it replaces the submit button with a scripted anchor tag. Everything else gets copied as-is from the HTML you paste.

Thanks also for posting a link on the MWPSK discussion board. I appreciate your bringing MWPSK to my attention. I had never heard of it, and I've been looking for a lightweight CMS for my customers. I was thinking about writing one of my own, but MWPSK may do the job. DNN is just too much for some of the customers I work with.

-- James

 

I have tried both converters to adjust the html for the aweber forms. I am unable to get the form functioning on the website.

-- Tim

Tim:

Thanks for taking the time to send feedback and letting me know about the trouble you are having with the AWeber converter. There have been two main reasons why you might have trouble with the converted code. The first is that the button script was designed to work with DotNetNuke, so it includes the following statement in the href JavaScript:

   theForm.__dnnVariable.value='';

You need to take that out if you are NOT hosting the AWeber form on a DotNetNuke site.

The second is that not all ASP.NET pages inject the script at the top of the page that defines "theForm". This usually happens if your page does not include any ASP.NET controls that cause a postback. You can tell if that is what's going on by doing a "view source" on the page from your browser. You should see the block of code shown below. If not, you can insert it yourself (put it right after the opening form tag):

  <script type="text/javascript">
  //<![CDATA[
  var theForm = document.forms['aspnetForm'];
  if (!theForm) {
      theForm = document.aspnetForm;
  }
  function __doPostBack(eventTarget, eventArgument) {
      if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
          theForm.__EVENTTARGET.value = eventTarget;
          theForm.__EVENTARGUMENT.value = eventArgument;
          theForm.submit();
      }
  }
  //]]>
  </script>

Keep in mind that you will need to remove this block of code if you later add posting controls to the page, because ASP.NET will want to put it in for itself.

Please let me know if either of these solutions does not solve your problem. Perhaps you've found a third scenario!

Thanks,
James Byrd