title: Why is the indexer on my .NET component not always accessible from VBScript?
body: <p>I have a .NET assembly which I am accessing from VBScript (classic ASP) via COM interop. One class has an indexer (a.k.a. default property) which I got working from VBScript by adding the following attribute to the indexer: <code>[DispId(0)]</code>. It works in most cases, but not when accessing the class as a member of another object.</p>
  
  <p>How can I get it to work with the following syntax: <code>Parent.Member("key")</code> where Member has the indexer (similar to accessing the default property of the built-in <code>Request.QueryString</code>: <code>Request.QueryString("key")</code>)?</p>
  
  <p>In my case, there is a parent class <code>TestRequest</code> with a <code>QueryString</code> property which returns an <code>IRequestDictionary</code>, which has the default indexer.</p>
  
  <p>VBScript example:</p>
  
  <pre><code>Dim testRequest, testQueryString
  Set testRequest = Server.CreateObject("AspObjects.TestRequest")
  Set testQueryString = testRequest.QueryString
  testQueryString("key") = "value"
  </code></pre>
  
  <p>The following line causes an error instead of printing "value". This is the syntax I would like to get working:</p>
  
  <pre><code>Response.Write(testRequest.QueryString("key"))
  </code></pre>
  
  <blockquote>
    <p>Microsoft VBScript runtime (0x800A01C2)<br>
    Wrong number of arguments or invalid property assignment: 'QueryString'</p>
  </blockquote>
  
  <p>However, the following lines <em>do</em> work without error and output the expected "value" (note that the first line accesses the default indexer on a temporary variable):</p>
  
  <pre><code>Response.Write(testQueryString("key"))
  Response.Write(testRequest.QueryString.Item("key"))
  </code></pre>
  
  <p>Below are the simplified interfaces and classes in C# 2.0. They have been registered via <code>RegAsm.exe /path/to/AspObjects.dll /codebase /tlb</code>:</p>
  
  <pre><code>[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
  public interface IRequest {
      IRequestDictionary QueryString { get; }
  }
  
  [ClassInterface(ClassInterfaceType.None)]
  public class TestRequest : IRequest {
      private IRequestDictionary _queryString = new RequestDictionary();
  
      public IRequestDictionary QueryString {
          get { return _queryString; }
      }
  }
  
  [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
  public interface IRequestDictionary : IEnumerable {
      [DispId(0)]
      object this[object key] {
          [DispId(0)] get;
          [DispId(0)] set;
      }
  }
  
  [ClassInterface(ClassInterfaceType.None)]
  public class RequestDictionary : IRequestDictionary {
      private Hashtable _dictionary = new Hashtable();
  
      public object this[object key] {
          get { return _dictionary[key]; }
          set { _dictionary[key] = value; }
      }
  }
  </code></pre>
  
  <p>I've tried researching and experimenting with various options but have not yet found a solution. Any help would be appreciated to figure out why the <code>testRequest.QueryString("key")</code> syntax is not working and how to get it working.</p>
  
  <p>Note: This is a followup to <a href="https://stackoverflow.com/questions/299251/exposing-the-indexer-default-property-via-com-interop">Exposing the indexer / default property via COM Interop</a>.</p>
  
  <p>Update: Here is some the generated IDL from the type library (using <a href="http://www.microsoft.com/downloads/details.aspx?familyid=9d467a69-57ff-4ae7-96ee-b18c4790cffd&amp;displaylang=en" rel="nofollow noreferrer">oleview</a>):</p>
  
  <pre><code>[
    uuid(C6EDF8BC-6C8B-3AB2-92AA-BBF4D29C376E),
    version(1.0),
    custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, AspObjects.IRequest)
  
  ]
  dispinterface IRequest {
      properties:
      methods:
          [id(0x60020000), propget]
          IRequestDictionary* QueryString();
  };
  
  [
    uuid(8A494CF3-1D9E-35AE-AFA7-E7B200465426),
    version(1.0),
    custom(0F21F359-AB84-41E8-9A78-36D110E6D2F9, AspObjects.IRequestDictionary)
  
  ]
  dispinterface IRequestDictionary {
      properties:
      methods:
          [id(00000000), propget]
          VARIANT Item([in] VARIANT key);
          [id(00000000), propputref]
          void Item(
                          [in] VARIANT key, 
                          [in] VARIANT rhs);
  };
  </code></pre>