Atlas Play: Using the AutoCompleteExtender with a Page Method (cleaner/simple version)

[out of date post... this deals with MS Atlas CTP... which has been change drastically and is now MS Ajax Extensions]

Ok, the code in yesterday’s post was ugly! I’ve come up with a simpler example that doesn’t use reflection, but it does require maintaining a switch…case/select…case.

I’m introducing a new helper class to do our heavy lifting, and an interface for calling back to the page (I can still can come up better solutions than this one… but it’s workable for me for now [so if you want to tweak it some more… knock yourself out… I’m done after this one])

Here’s the interface that the page will implement-

public interface IAtlasAutoCompletePage
{
  
string[] ExecuteMethod(string MethodName, string prefixText, int count);
}

One method that let’s us tell the page which Autocomplete function we want to call and the normal Autocomplete parameters.  I imagine you could probably build a method using delegates and a custom object/generic collection that would do away with both this interface and the implementation’s case statement (that will be up to you).

Here’s a page’s codebehind (BTW, the see yesterday’s post for the html part of the page).

using System;
using System.Collections.Generic;
using System.Data;
using System.Configuration;
using System.Collections;
using System.IO;
using System.Reflection;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Web.Services;
using Microsoft.Web.Script.Serialization;

public partial class AutoCompleteWithNoWS : System.Web.UI.Page, IAtlasAutoCompletePage
{
  
protected void Page_Load(object sender, EventArgs e)
   {
     
try
     
{
        
AtlasAutoCompleteHelper helpme = new AtlasAutoCompleteHelper(this);
      } 
     
catch
     
{
        
// Do something with the exception... 
        
// use the logger of your choice is a good recommendation
     
}
   }

   [WebMethod(true)]
  
public string[] GetAutoComplete(string prefixText, int count)
   {
     
string[] result;
     
if (prefixText.Length > 8) return new string[0];
      result =
new string[4];
      result[0] = prefixText +
"AAAAAAAA";
      result[1] = prefixText +
"DDDDDDDD";
      result[2] = prefixText +
"MMMMMMMM";
      result[3] = prefixText +
"VVVVVVVV";
     
return result;
   }

   public string[] ExecuteMethod(string MethodName, string prefixText, int count)
   {
     
switch (MethodName)
      {
        
case "GetAutoComplete":
           
return GetAutoComplete(prefixText, count);
        
default:
           
return new string[0];
      }
   }
}

Really there is only a couple changes from yesterday’s code.  First of all the Page Load simply instantiates the AtlasAutoCompleteHelper class passing an instance of itself.  I could have built this as a Base class, but I’ve found that the inheritance tree can be a pain (especially when you don’t want to always include a feature… this means you have 2 different page inheritance trees and you have make sure that changes in one tree get populated in the other, etc… it can be a pain)

Here’s the AtlasAutoCompleteHelper class (which does the heavy lifting for us)

using System;
using System.Collections.Generic;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using Microsoft.Web.Script.Serialization;

/// <summary>
///
Summary description for AtlasAutoCompleteHelper
/// </summary>
public class AtlasAutoCompleteHelper
{
   private Page page;

  
public AtlasAutoCompleteHelper(Page pg)
   {
      page = pg;
     
if (isAutoCompleteWSCall())
      {
         CallPageAutoComplete();
      }
   }

   private void CallPageAutoComplete()
   {
     
string output = "";
     
try
     
{
        
byte[] buffer = new byte[page.Request.InputStream.Length];
         page.Request.InputStream.Read(buffer, 0, buffer.Length);
        
string inputString = new string(System.Text.UTF8Encoding.UTF8.GetChars(buffer));
        
Dictionary<string, object> ParamsFromJS =
             Microsoft.Web.Script.Serialization.
JavaScriptObjectDeserializer.Deserialize(inputString) 
                 
as Dictionary<string, object>;

         IAtlasAutoCompletePage pg = page as IAtlasAutoCompletePage;
         output =
JavaScriptObjectSerializer.Serialize(
              
pg.ExecuteMethod(page.Request.QueryString["mn"].ToString(), 
                     ParamsFromJS[
"prefixText"] as string , (int)ParamsFromJS["count"]));

      }
     
finally
     
{
         page.Response.Clear();
         page.Response.ContentType =
"application/json";
         page.Response.Write(output);
         page.Response.End();   
     
}
   }

 

   private bool isAutoCompleteWSCall()
   {
     
return (page.Request.QueryString["mn"] != null && 
              
page.Request.ServerVariables["HTTP_CONTENT_TYPE"] == "application/json");
   }
}

 So there are 2 methods plus an intializer in our helper class.    The isAutoCompleteWSCall determines whether this is a call to an AutoComplete function.  It checks for the mn querystring and JSON content.. NOTE: postback is not checked… AutoComplete calls aren’t postbacks!  Remember this! That means that your form fields have NOT been transferred back… Code your AutoComplete functions accordingly!  [yes, I’m shouting on purpose…. I want to save you some pain… BTW, Session is available if you need some state mechanism <wink />]

The initializer stores the page instance in a private variable, calls the isAutoCompleteWSCall to check to see if this is an Autocomplete call.  If it is then the CallPageAutoComplete method is called.

CallPageAutoComplete reads the JSON string from the inputStream of the Request object, and deserialize the string into a Generic dictionary (just like yesterday).  The generic dictionary object is used to populate the parameters for the call to the page’s IAtlasAutoCompletePage interface’s ExecuteMethod.  The result is re-serialized to a JSON string, sent back to the page (after setting the content type to JSON), and then the request is stopped.

There are probably a couple enhancements you could make to this example (I’m done with it as previously mentioned).  You might want to create a class that takes a method name and a delegate), and pass a generic collection of these to the helper function instead of using the interface.  This would probably be a little cleaner, but you will either need to use Reflection or maintain a list of functions to call. 

BTW, one of the benefits that I can see to this version (although I have yet to try) is that you don’t need to use the WebMethods Attribute… although I would recommend it.  I suspect that this example will be unneeded in future versions of Atlas.

 

[tags: Atlas, ASP.Net, Ajax] 

Print | posted on Wednesday, May 03, 2006 2:08 PM

Feedback

# re: Atlas Play: Using the AutoCompleteExtender with a Page Method (cleaner/simple version)

left by at 5/3/2006 3:42 PM Gravatar

Hi Jay,

I'm not sure I understand why you need to add the AtlasAutoCompleteHelper.  You should/will just be able to have the [webmethod] method and that is all.

Hope this helps,

Scott

# re: Atlas Play: Using the AutoCompleteExtender with a Page Method (cleaner/simple version)

left by at 5/3/2006 5:21 PM Gravatar

Scott,

When I tried with just the webmethod and the HTML design (from yesterday's code).  The post to the page is happening, but webmethod tagged code is not run.

So I worked out my own method <grin />.  As noted all over the place this is admittedly a temporary example.  I will try again and will post the code to the forums if it's not working... maybe I missed something...

# re: Atlas Play: Using the AutoCompleteExtender with a Page Method (cleaner/simple version)

left by at 5/4/2006 1:21 AM Gravatar

Jay, Scott is right, why do you need to write all that code? Maybe I'm missing something, but what's wrong with this: atlas.asp.net/.../ServerAutoComplete.aspx ?

# re: Atlas Play: Using the AutoCompleteExtender with a Page Method (cleaner/simple version)

left by at 5/4/2006 12:47 PM Gravatar

Simone,

See this post -- forums.asp.net/.../1275505.aspx

I want to use a page method instead of a Web Service... The tutorial you point at is the WebService tutorial...

Jay

# re: Atlas Play: Using the AutoCompleteExtender with a Page Method (cleaner/simple version)

left by at 5/4/2006 1:17 PM Gravatar

Sorry Jay, I missed the point :)

Didn't try it yet, but I guess they're still working on it...

# re: Atlas Play: Using the AutoCompleteExtender with a Page Method (cleaner/simple version)

left by at 6/14/2006 10:10 PM Gravatar

Is it a must for GetAutoComplete to be WebMethod?

Thanks

# re: Atlas Play: Using the AutoCompleteExtender with a Page Method (cleaner/simple version)

left by at 6/15/2006 2:06 PM Gravatar

Albert,

Go read the beginning of this post (theruntime.com/.../143525.aspx)

You are probably thinking WebMethod as in WebService... Microsoft repurposed the WebMethod attribute for Atlas... the post I pointed you to talks about using Atlas as a Page Method Callback Library.

# re: Atlas Play: Using the AutoCompleteExtender with a Page Method (cleaner/simple version)

left by at 7/12/2006 11:12 PM Gravatar

This could be a handy workaround, BUT ... this should really be changed by Microsoft to handle PageMethods!!!  The CascadingDropDown (atlas toolkit) also only worked with a Web Service originally but now works with page methods by just leaving out the ServicePath tag, and having a WebMethod on your code behind.  This works really well now.  Is the AutoCompleteExtender likely to support the same soon (or does it already in some way)?  

# re: Atlas Play: Using the AutoCompleteExtender with a Page Method (cleaner/simple version)

left by at 7/12/2006 11:52 PM Gravatar

Sam,

Check back on my blog after this weekend.  I'm speaking at CodeCamp this weekend and am sitting on something.  I have a better solution than this one...

Jay

Title  
Name
Email (never displayed)
Url
Comments   
Please add 8 and 7 and type the answer here: