Cannot access Soapheader in SoapExtension

Discussion in 'ASP .Net Web Services' started by Andy Kendall, Sep 6, 2006.

  1. Andy Kendall

    Andy Kendall Guest

    I have a problem accessing my custom SoapHeader from a SoapExtension. My
    extension has no compile time reference to the class derived from
    SoapHeader, so how can cast it into a SoapHeader of the correct type?


    Thanks,

    Andy
     
    Andy Kendall, Sep 6, 2006
    #1
    1. Advertising

  2. "Andy Kendall" <> wrote in message
    news:%...
    >I have a problem accessing my custom SoapHeader from a SoapExtension. My
    > extension has no compile time reference to the class derived from
    > SoapHeader, so how can cast it into a SoapHeader of the correct type?


    XML.

    John
     
    John Saunders, Sep 6, 2006
    #2
    1. Advertising

  3. Andy Kendall

    Andy Kendall Guest

    Care to elaborate? Do you mean XML deserialization?

    "John Saunders" <john.saunders at trizetto.com> wrote in message
    news:...
    > "Andy Kendall" <> wrote in message
    > news:%...
    > >I have a problem accessing my custom SoapHeader from a SoapExtension. My
    > > extension has no compile time reference to the class derived from
    > > SoapHeader, so how can cast it into a SoapHeader of the correct type?

    >
    > XML.
    >
    > John
    >
    >
     
    Andy Kendall, Sep 7, 2006
    #3
  4. "Andy Kendall" <> wrote in message
    news:%...
    > Care to elaborate? Do you mean XML deserialization?
    >
    > "John Saunders" <john.saunders at trizetto.com> wrote in message
    > news:...
    >> "Andy Kendall" <> wrote in message
    >> news:%...
    >> >I have a problem accessing my custom SoapHeader from a SoapExtension. My
    >> > extension has no compile time reference to the class derived from
    >> > SoapHeader, so how can cast it into a SoapHeader of the correct type?

    >>
    >> XML.
    >>


    Ok, I apologize. I thought I had a SOAP Extension which was accessing the
    headers as XML. I was mistaken, it accesses them as a SoapHeader-derived
    object.

    So, to your question: I don't understand how a class, "A", without a
    compile-time reference to another class, "B", could cast an object to an
    instance of class "B". This question is independent of SOAP Extensions and
    Headers. In fact, once it had been cast to class "B", how would class "A"
    reference the methods, fields, etc., of class "B" if it has no compile-time
    reference to it?

    I think more detail is required.

    John
     
    John Saunders, Sep 7, 2006
    #4
  5. Andy Kendall

    Andy Kendall Guest

    Well, given that only xml data is being transferred between client and
    server, I wondered if it was possible to create an identical class
    definition and cast it into that. After all, normally when you create a web
    service and a client VS generates the server and client proxy class and it
    works fine - these two classes are not the same - i.e. No binary .dll or
    similar has to be shared between client and server but you can use
    DirectCast on the base class as if they were.

    I tried creating an identical SoapHeader class in my SoapExtension project
    in an identical namespace but it complains with "invalid cast" It makes me
    wonder how the runtime knows that the xml representaion of my soapHeader
    class coming over the wire is not based on the one defined in my
    SoapExtension priject but on the SoapHeader defined on the web service
    instead - does the deserialised XML have some kind of guid or reference to
    the assembly?

    I can do what I need to do by adding a reference to the web service .dll
    file into my SoapExtension project, but I would rather not have that
    dependancy. I also suspect you can do it with manual deserialisation (?) I
    just wondered if there was an easier way.

    Incidentally, I also notice there is no way to access the raw XML from the
    base SoapHeader class, otherwise I would have just used that.

    "John Saunders" <john.saunders at trizetto.com> wrote in message
    news:%...
    > "Andy Kendall" <> wrote in message
    > news:%...
    > > Care to elaborate? Do you mean XML deserialization?
    > >
    > > "John Saunders" <john.saunders at trizetto.com> wrote in message
    > > news:...
    > >> "Andy Kendall" <> wrote in message
    > >> news:%...
    > >> >I have a problem accessing my custom SoapHeader from a SoapExtension.

    My
    > >> > extension has no compile time reference to the class derived from
    > >> > SoapHeader, so how can cast it into a SoapHeader of the correct type?
    > >>
    > >> XML.
    > >>

    >
    > Ok, I apologize. I thought I had a SOAP Extension which was accessing the
    > headers as XML. I was mistaken, it accesses them as a SoapHeader-derived
    > object.
    >
    > So, to your question: I don't understand how a class, "A", without a
    > compile-time reference to another class, "B", could cast an object to an
    > instance of class "B". This question is independent of SOAP Extensions and
    > Headers. In fact, once it had been cast to class "B", how would class "A"
    > reference the methods, fields, etc., of class "B" if it has no

    compile-time
    > reference to it?
    >
    > I think more detail is required.
    >
    > John
    >
    >
     
    Andy Kendall, Sep 7, 2006
    #5
  6. "Andy Kendall" <> wrote in message
    news:...
    > Well, given that only xml data is being transferred between client and
    > server, I wondered if it was possible to create an identical class
    > definition and cast it into that. After all, normally when you create a
    > web
    > service and a client VS generates the server and client proxy class and it
    > works fine - these two classes are not the same - i.e. No binary .dll or
    > similar has to be shared between client and server but you can use
    > DirectCast on the base class as if they were.


    Ok, now, note that I haven't quite tried what I'm going to suggest. The
    closest I've come to this had to do with SOAP faults.

    If the SOAP Extension and the Web Service both access the same SOAP header,
    then the definition of the SOAP Header should be in a common place. Perhaps
    you can separate out the schema for the SOAP Header, and put the schema,
    along with the code generated from the schema, into a separate project. That
    project would "own" the piece of schema which defines these SOAP Headers.

    This project would be referenced by the web service and by the SOAP
    Extension.

    I've done something similar with SOAP faults, which needed to be accessed
    both by one web service and by some code common amongst several web
    services. The schema, the generated classes, and the code to create
    instances of the SOAP faults was all located in the common project.

    I hope this helps. Please let us know how it works out. I don't yet have a
    SOAP Header which is shared, but that might happen.

    John
     
    John Saunders, Sep 7, 2006
    #6
  7. Andy Kendall

    Andy Kendall Guest

    Thanks for the reply John,

    I think what you suggest is the ideal way forward, however, our situation is
    that the SoapExtension in question is just a temporary fix to be applied to
    an existing live webservice. On the next build cycle, I think we will
    seperate out as you suggest. As our SoapHeader was defined as public,
    luckily I have been able to add a reference to the webservice .dll file so
    it gets round the problem.

    I'm still intrigued as to how visual studio/ASP.NET does it though. I mean,
    in a normal visual studio scenario, you create you webservice with any
    soapheaders, then you add a reference to that service from a client app. The
    proxy classes generated on the client for the soapheaders are completly
    different classes from the soapheader classes on the server and yet you can
    create instances of them on the client, send them accross the wire and cast
    them back into the correct type on the server and it all works swimmingly.
    How does the runtime know not to throw an invalid cast exception?


    "John Saunders" <john.saunders at trizetto.com> wrote in message
    news:...
    > "Andy Kendall" <> wrote in message
    > news:...
    > > Well, given that only xml data is being transferred between client and
    > > server, I wondered if it was possible to create an identical class
    > > definition and cast it into that. After all, normally when you create a
    > > web
    > > service and a client VS generates the server and client proxy class and

    it
    > > works fine - these two classes are not the same - i.e. No binary .dll or
    > > similar has to be shared between client and server but you can use
    > > DirectCast on the base class as if they were.

    >
    > Ok, now, note that I haven't quite tried what I'm going to suggest. The
    > closest I've come to this had to do with SOAP faults.
    >
    > If the SOAP Extension and the Web Service both access the same SOAP

    header,
    > then the definition of the SOAP Header should be in a common place.

    Perhaps
    > you can separate out the schema for the SOAP Header, and put the schema,
    > along with the code generated from the schema, into a separate project.

    That
    > project would "own" the piece of schema which defines these SOAP Headers.
    >
    > This project would be referenced by the web service and by the SOAP
    > Extension.
    >
    > I've done something similar with SOAP faults, which needed to be accessed
    > both by one web service and by some code common amongst several web
    > services. The schema, the generated classes, and the code to create
    > instances of the SOAP faults was all located in the common project.
    >
    > I hope this helps. Please let us know how it works out. I don't yet have a
    > SOAP Header which is shared, but that might happen.
    >
    > John
    >
    >
     
    Andy Kendall, Sep 8, 2006
    #7
  8. "Andy Kendall" <> wrote in message
    news:...
    > Thanks for the reply John,
    >
    > I think what you suggest is the ideal way forward, however, our situation
    > is
    > that the SoapExtension in question is just a temporary fix to be applied
    > to
    > an existing live webservice. On the next build cycle, I think we will
    > seperate out as you suggest. As our SoapHeader was defined as public,
    > luckily I have been able to add a reference to the webservice .dll file so
    > it gets round the problem.
    >
    > I'm still intrigued as to how visual studio/ASP.NET does it though. I
    > mean,
    > in a normal visual studio scenario, you create you webservice with any
    > soapheaders, then you add a reference to that service from a client app.
    > The
    > proxy classes generated on the client for the soapheaders are completly
    > different classes from the soapheader classes on the server and yet you
    > can
    > create instances of them on the client, send them accross the wire and
    > cast
    > them back into the correct type on the server and it all works swimmingly.
    > How does the runtime know not to throw an invalid cast exception?


    It doesn't know. The cast is not invalid. It does not send instances across
    the wire. It serializes a client instance, sends it across the wire, then
    deserializes it into a totally separate server instance, which is of a type
    unrelated to the type of the client instance.

    No objects are ever transmitted in web services. Just XML.

    John
     
    John Saunders, Sep 8, 2006
    #8
  9. Andy Kendall

    Andy Kendall Guest

    Sure, but then whats different about that scenario and the one I first tried
    where I had an identical class definition (with same namespace) in my soap
    extension project?

    I know there must be something in the serialised xml telling the runtime
    that the serialised soapheader represents the soapheader class defined in my
    web service and not the (identical) one defined in the soapextension
    assembly - but I don't know what it is.



    >
    > It doesn't know. The cast is not invalid. It does not send instances

    across
    > the wire. It serializes a client instance, sends it across the wire, then
    > deserializes it into a totally separate server instance, which is of a

    type
    > unrelated to the type of the client instance.
    >
    > No objects are ever transmitted in web services. Just XML.
    >
    > John
    >
    >
     
    Andy Kendall, Sep 8, 2006
    #9
  10. "Andy Kendall" <> wrote in message
    news:...
    > Sure, but then whats different about that scenario and the one I first
    > tried
    > where I had an identical class definition (with same namespace) in my soap
    > extension project?
    >
    > I know there must be something in the serialised xml telling the runtime
    > that the serialised soapheader represents the soapheader class defined in
    > my
    > web service and not the (identical) one defined in the soapextension
    > assembly - but I don't know what it is.


    I'm not sure of the step by step details, but it's something like this:

    1) IIS receives a request directed at some file with a .asmx extension
    2) Since there's a sctipt mapping between that extension and ASP.NET, the
    request is sent to the ASP.NET worker process
    3) The worker process looks at the file extension, and maps it to a
    HttpHandler subclass, in this case, WebServiceHandler (I think)
    4) WebServiceHandler opens the .asmx file and, based on its contents,
    determines which WebService-derived class to use.
    5) Based on the metadata on this class, it matches the incoming SOAP message
    to a WebMethod
    6) Based on the metadata on this WebMethod, it deserializes the SOAP message
    6a) You have one or more [SoapHeader] attributes on your WebMethods, right?
    6b) Each SoapHeader attribute refers to a public field in your WebService.
    6c) The field has a type and maybe other attributes, which guide
    deserialization of any matching SOAP headers in the message

    So, no magic, just a bit of work going on in the background.

    John
     
    John Saunders, Sep 8, 2006
    #10
  11. Andy Kendall

    Andy Kendall Guest

    John, Thanks for the reply. I have found some more information which answers
    my query:

    When you specifiy a soapHEader on a web method you use the SoapHeader
    attribute specifiying the name of your SoapHeader derived class. It doesn't
    matter what namespace the proxy or server class lives in because it is just
    plain serialised/deserialised, as you quite rightly say - there is no magic
    going on.

    What was confusing me was why when I tried to access the soapHeader from a
    soap extension I couldn't cast into the correct type of soapHeader unless I
    referenced the original web service project .dll.

    I now understand my mistake. In the web service, ASP is handling the
    serialising, but in the soap extension ASP has only deserialised the headers
    to the base type i.e. SoapHeader and not the original derived soapHeader.
    This of course makes sense and what I was trying to do was just a plain
    invalid cast exception.


    Cheers for your help


    "John Saunders" <john.saunders at trizetto.com> wrote in message
    news:...
    > "Andy Kendall" <> wrote in message
    > news:...
    > > Sure, but then whats different about that scenario and the one I first
    > > tried
    > > where I had an identical class definition (with same namespace) in my

    soap
    > > extension project?
    > >
    > > I know there must be something in the serialised xml telling the runtime
    > > that the serialised soapheader represents the soapheader class defined

    in
    > > my
    > > web service and not the (identical) one defined in the soapextension
    > > assembly - but I don't know what it is.

    >
    > I'm not sure of the step by step details, but it's something like this:
    >
    > 1) IIS receives a request directed at some file with a .asmx extension
    > 2) Since there's a sctipt mapping between that extension and ASP.NET, the
    > request is sent to the ASP.NET worker process
    > 3) The worker process looks at the file extension, and maps it to a
    > HttpHandler subclass, in this case, WebServiceHandler (I think)
    > 4) WebServiceHandler opens the .asmx file and, based on its contents,
    > determines which WebService-derived class to use.
    > 5) Based on the metadata on this class, it matches the incoming SOAP

    message
    > to a WebMethod
    > 6) Based on the metadata on this WebMethod, it deserializes the SOAP

    message
    > 6a) You have one or more [SoapHeader] attributes on your WebMethods,

    right?
    > 6b) Each SoapHeader attribute refers to a public field in your WebService.
    > 6c) The field has a type and maybe other attributes, which guide
    > deserialization of any matching SOAP headers in the message
    >
    > So, no magic, just a bit of work going on in the background.
    >
    > John
    >
    >
     
    Andy Kendall, Sep 22, 2006
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. All Smiles

    SoapHeader problem

    All Smiles, May 20, 2004, in forum: ASP .Net
    Replies:
    0
    Views:
    334
    All Smiles
    May 20, 2004
  2. Replies:
    0
    Views:
    388
  3. Replies:
    0
    Views:
    324
  4. Replies:
    0
    Views:
    384
  5. SoapExtension and SoapHeader

    , Mar 5, 2007, in forum: ASP .Net Web Services
    Replies:
    1
    Views:
    173
Loading...

Share This Page