问题
the problem almost like this: ASP.NET Web Service changes port on Invoke.I try to use the SoapExtensionReflector to modify the service address in WSDL,and it works on SaopAddress,but the http address is still nochanging. the result like this:
- <wsdl:service name="WebService1">
- <wsdl:port name="WebService1Soap" binding="tns:WebService1Soap">
<soap:address location="http://I can remove this Port:3821/WebService1.asmx" />
</wsdl:port>
- <wsdl:port name="WebService1Soap12" binding="tns:WebService1Soap12">
<soap12:address location="http://I can remove this Port:3821/WebService1.asmx" />
</wsdl:port>
- <wsdl:port name="WebService1HttpGet" binding="tns:WebService1HttpGet">
<http:address location="http://localhost:3821/WebService1.asmx" />
</wsdl:port>
- <wsdl:port name="WebService1HttpPost" binding="tns:WebService1HttpPost">
<http:address location="http://localhost:3821/WebService1.asmx" />
</wsdl:port>
</wsdl:service>
we can see that the soap location has been changed but the last two http:address location are still Unchanged.
here is my code:
public class OuterPortReflector : SoapExtensionReflector
{
public override void ReflectMethod()
{
}
public override void ReflectDescription()
{
ServiceDescription description = ReflectionContext.ServiceDescription;
foreach (Service service in description.Services)
{
foreach (Port port in service.Ports)
{
if (!portsName.ContainsKey(port.Binding.Name))
{
portsName.Add(port.Binding.Name, true);
}
foreach (ServiceDescriptionFormatExtension extension in port.Extensions)
{
SoapAddressBinding binding = extension as SoapAddressBinding;
if (null != binding)
{
binding.Location = binding.Location.Replace("http://localhost", "http://I can remove this Port");
}
else
{
HttpAddressBinding httpBinding = extension as HttpAddressBinding;
if (httpBinding != null)
{
httpBinding.Location = httpBinding.Location.Replace("http://localhost", "http://I can remove this Port");
}
else
{
Soap12AddressBinding soap12Binding = extension as Soap12AddressBinding;
if (soap12Binding != null)
{
soap12Binding.Location = soap12Binding.Location.Replace("http://localhost", "http://I can remove this Port");
}
}
}
}
}
}
}
}
How to deal with this? Is there something wrong with my code?
hope somebady can give me some suggestion or keywords.3Q
回答1:
if (null != binding)
if (httpBinding != null)
if (soap12Binding != null)
Can you try using Equals(Object) method defined by this SoapAddressBinding class, instead of comparing it directly with null as string. For example in your case,use
if(!binding.Equals(null))
if(!httpbinding.Equals(null))
if (!soap12Binding.Equals(null))
Few platform don't work for direct comparision of string , always try to use Equals() method while comparing string.
回答2:
The only way I could accomplish is to use HttpModule. In intercepts every request and changes the response for WSDL.
public class WsdlFixHttpModule : IHttpModule
{
private static string _webServicesBaseUrl;
public static WsdlFixHttpModule()
{
_webServicesBaseUrl = ConfigurationManager.AppSettings("BaseWebServicesUrl");
}
public void Init(HttpApplication context)
{
context.EndRequest += (s, e) => OnEndRequest(s, e);
context.BeginRequest += (s, e) => OnBeginRequest(s, e);
}
private void OnBeginRequest(object sender, EventArgs e)
{
HttpContext httpContext = HttpContext.Current;
if ((!string.IsNullOrWhiteSpace(_webServicesBaseUrl) & httpContext.Request.RawUrl.EndsWith("YourService.asmx?wsdl", StringComparison.InvariantCultureIgnoreCase)))
httpContext.Response.Filter = new StreamWatcher(httpContext.Response.Filter);
}
private void OnEndRequest(object sender, EventArgs e)
{
HttpContext httpContext = HttpContext.Current;
if ((!string.IsNullOrWhiteSpace(_webServicesBaseUrl) & httpContext.Request.RawUrl.EndsWith("YourService.asmx?wsdl", StringComparison.InvariantCultureIgnoreCase)))
{
string wsdl = httpContext.Response.Filter.ToString();
wsdl = Regex.Replace(wsdl, @"(?<=address location="")(.*)(?=\/YourService.asmx"")", _webServicesBaseUrl);
httpContext.Response.Clear();
httpContext.Response.Write(wsdl);
httpContext.Response.End();
}
}
public void Dispose()
{
}
}
Here is StreamWatcher
that is used to read default response.
public class StreamWatcher : Stream
{
private Stream _base;
private MemoryStream _memoryStream = new MemoryStream();
public StreamWatcher(Stream stream)
{
_base = stream;
}
public override void Flush()
{
_base.Flush();
}
public override int Read(byte[] buffer, int offset, int count)
{
return _base.Read(buffer, offset, count);
}
public override void Write(byte[] buffer, int offset, int count)
{
_memoryStream.Write(buffer, offset, count);
_base.Write(buffer, offset, count);
}
public override string ToString()
{
return Encoding.UTF8.GetString(_memoryStream.ToArray());
}
public override bool CanRead
{
get
{
throw new NotImplementedException();
}
}
public override bool CanSeek
{
get
{
throw new NotImplementedException();
}
}
public override bool CanWrite
{
get
{
throw new NotImplementedException();
}
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotImplementedException();
}
public override void SetLength(long value)
{
throw new NotImplementedException();
}
public override long Length
{
get
{
throw new NotImplementedException();
}
}
public override long Position
{
get
{
throw new NotImplementedException();
}
set
{
throw new NotImplementedException();
}
}
}
And HttpModule
needs to be registered in the web.config
来源:https://stackoverflow.com/questions/20969363/how-to-modify-the-httpaddress-in-wsdl