c# - WCF Binding SOAP 1.1 requests with both "application/xml" and "text/xml" ContentTypes -
i attempting replace legacy soap 1.1 web service new wcf service.
there many existing clients , not feasible change them.
i've created service , works clients 1 vexing exception.
since old service soap 1.1, tried used basichttpbinding, like:
<bindings> <basichttpbinding> <binding name="whatever" /> </basichttpbinding> </bindings>
most of inbound messages following example, , works fine:
post http://mysoapwebserviceurl/service.svc http/1.1 soapaction: dosomething content-type: text/xml;charset=utf-8 content-length: 1234 host: mysoapwebserviceurl <soap:envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"> <soap:body soap:encodingstyle="http://schemas.xmlsoap.org/soap/encoding/"> <xml:inputstuffhere /> </soap:body> </soap:envelope>
my issue couple of callers sending same message except content-type of 'application/xml' in headers, , receiving error:
error: 415 cannot process message because content type 'application/xml' not expected type 'text/xml'.
i've tried switching binding wshttpbinding
or webhttpbinding
.
however, cannot find combination of settings on either of bindings allow content types of both 'application/xml' , 'text/xml' , soap 1.1 style "soapaction" addressing in header.
i've tried implement custom text message encoder, starting microsoft's wcf example customtextmessageencodingelement
.
however, using custom text messaging encoder can set mediatype
either 'application/xml' or 'text/xml'. but, not surprisingly, clients sending specified content-type succeed clients using other content-type fail.
i've attempted set mediatype
including wildcard '*/xml'
, fails callers.
is there way create wcf binding service accept content type of either 'application/xml' or 'text/xml'?
i believe trying impossible.
i have concluded wcf inappropriate technology implementing backwards-compatible replacement legacy soap web service allowed various content-type values in headers.
instead, have implemented custom httpmodule using system.web.ihttpmodule.
basic implementation details follow, else has found down rabbit hole , needs way out.
code:
public class mycustomhttpmodule : ihttpmodule { public void init(httpapplication context) { context.beginrequest += onbegin; } private void onbegin(object sender, eventargs e) { var app = (httpapplication) sender; var context = app.context; if (context.request.httpmethod == "post") { string soapactionheader = context.request.headers["soapaction"]; byte[] buffer = new byte[context.request.inputstream.length]; context.request.inputstream.read(buffer, 0, buffer.length); context.request.inputstream.position = 0; string rawrequest = encoding.ascii.getstring(buffer); var soapenvelope = new xmldocument(); soapenvelope.loadxml(rawrequest); string response = dosomemagic(soapactionheader, soapenvelope); context.response.contenttype = "text/xml"; context.response.contentencoding = encoding.utf8; context.response.write(response); } else { //do else //returning wsdl file appropriate request nice } context.response.flush(); context.response.suppresscontent = true; context.applicationinstance.completerequest(); } private string dosomemagic(string soapactionheader, xmldocument soapenvelope) { //magic happens here } public void dispose() { //nothing happens here //a dispose() implementation required ihttpmodule interface } }
web.config:
<system.webserver> <modules runallmanagedmodulesforallrequests="true"> <add name="mycustomhttpmodule" type="appropriatenamespace.mycustomhttpmodule"/> </modules> </system.webserver>
Comments
Post a Comment