C# ASMX SOAP服务改造:移除Method节点并迁移SOAPHeader
Got it, let's work through this—your issue comes from mixing WCF's MessageContract attributes with ASMX, which uses a totally different model for defining SOAP structures. ASMX doesn't recognize WCF's MessageHeader or MessageContract at all, so we need to refactor the code to use ASMX-compatible tools and attributes.
Step 1: Refactor Entity Classes (Strip Out WCF Stuff)
First, get rid of all WCF-specific attributes—they don't play nice with ASMX. Instead, use standard XML serialization attributes and split the header into its own standalone class (since ASMX handles headers via the SoapHeader attribute, not embedded in request objects).
// SOAP Header Request class (will live in soap:Header) [Serializable] [XmlType(Namespace = "http://www.foo.com/schemas/method")] public class SOAPHeaderRequest { // Add your actual header properties here (e.g., authentication tokens) public string AuthToken { get; set; } } // SOAP Header Response class [Serializable] [XmlType(Namespace = "http://www.foo.com/schemas/method")] public class SOAPHeaderResponse { // Add your response header properties here public string StatusCode { get; set; } } // Request Body class (will sit directly under soap:Body) [Serializable] [XmlType(Namespace = "http://www.foo.com/schemas/method")] public class Body { public string Property { get; set; } } // Response object (matches desired structure without extra wrappers) [Serializable] [XmlType(Namespace = "http://www.foo.com/schemas/method")] public class ResponseObject { public Body body { get; set; } }
Step 2: Adjust the Service Interface (Optional but Clean)
If you want to keep using an interface for consistency, update it to fit the ASMX model (WCF's ServiceContract is optional here, but it's fine to keep for structure):
[ServiceContract(Namespace = "http://www.foo.com/schemas/method")] public interface IServiceContract { [OperationContract(Action = "http://www.foo.com/schemas/method/method")] ResponseObject Method(Body requestBody); }
Step 3: Rewrite the ASMX Service Class
This is the critical part. Use the SoapHeader attribute to bind your header class to a service member, and make the WebMethod accept the Body directly (not wrapped in a RequestObject). This will eliminate the outer Method wrapper node and move the header to the correct soap:Header section.
[WebService(Namespace = "http://www.foo.com/schemas/method")] [WebServiceBinding(ConformsTo = WsiProfiles.None)] public class M5NapaPartUpdateService : WebService, IServiceContract { // Incoming SOAP header (bound via SoapHeader attribute) [SoapHeader("SOAPHeaderRequest", Direction = SoapHeaderDirection.In)] public SOAPHeaderRequest SOAPHeaderRequest; // Outgoing response header [SoapHeader("SOAPHeaderResponse", Direction = SoapHeaderDirection.Out)] public SOAPHeaderResponse SOAPHeaderResponse; [WebMethod] [SoapMethod(SoapAction = "http://www.foo.com/schemas/method/method")] public ResponseObject Method(Body requestBody) { // Initialize response header (add your logic here) SOAPHeaderResponse = new SOAPHeaderResponse { StatusCode = "OK" }; // Your business logic goes here (process requestBody) return new ResponseObject { body = requestBody }; } }
Why This Works
- No More Wrapper Node: By passing
Bodydirectly to the WebMethod instead of a wrapperRequestObject, ASMX won't generate an outerMethodelement around the request body. - Header in soap:Header: The
SoapHeaderattribute tells ASMX to serialize theSOAPHeaderRequestmember into thesoap:Headerblock, not the body. - Namespace Consistency: We kept the target namespace identical across all classes to match your required WSDL structure.
Verify with SoapUI
After deploying the updated service, generate a new request in SoapUI—you should see exactly what you need:
SOAPHeaderRequestnested inside thesoap:Headerelement- The
Bodyelement directly undersoap:Body, with no extra outer wrapper nodes
内容的提问来源于stack exchange,提问作者Fix

