C# 如何在SoapHttpClientProtocol中设置用户代理头?
我正在调用ASP.NET MVC4中的第三方SOAP服务(Magento webstore)。导入web服务引用时,所有服务方法都由Visual Studio自动实现,例如登录soap方法实现为C# 如何在SoapHttpClientProtocol中设置用户代理头?,c#,asp.net-mvc,soap,user-agent,soaphttpclientprotocol,C#,Asp.net Mvc,Soap,User Agent,Soaphttpclientprotocol,我正在调用ASP.NET MVC4中的第三方SOAP服务(Magento webstore)。导入web服务引用时,所有服务方法都由Visual Studio自动实现,例如登录soap方法实现为 public string login(string username, string apiKey) { object[] results = this.Invoke("login", new object[] { username,
public string login(string username, string apiKey) {
object[] results = this.Invoke("login", new object[] {
username,
apiKey});
return ((string)(results[0]));
}
但是当我调用此方法时,this.Invoke
发送一篇帖子,其中自动添加了此用户代理标题:
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0;
MS Web Services Client Protocol 4.0.30319.18444)
此标头告诉第三方用户代理是IE6。许多网站会自动屏蔽IE6,并显示一条消息,大意是“我们不支持IE6。去买一个真正的浏览器,再试一次”
所以soap调用中断,但这只是因为第三方站点认为我们正在使用IE6,而不是因为soap调用有任何问题。如果我们可以改变这个标题来模仿现代web浏览器的UA字符串,那么这个问题就不存在了
那么,如何更改SoapHttpClientProtocol方法调用所使用的UA字符串呢?这一切都发生在.NET核心的this.Invoke方法内部
编辑:
上面自动生成的代码中的对象this
是SoapHttpClientProtocol
的子类,因此是的,我可以自己在其中手动编写用户代理:
public string login(string username, string apiKey) {
this.UserAgent = "something, anything except for IE6";
object[] results = this.Invoke("login", new object[] {
username,
apiKey});
return ((string)(results[0]));
}
但是,这是自动生成的代码,在第三方更新其服务时会被覆盖(对于Magento来说,这是非常频繁的),我必须手动将其添加到每个自动生成的函数中(很多)。因此,在这里编写this.UserAgent=“not IE6”
是不实际的,它需要一个更有用的解决方案。自动生成的类是部分类吗
当它是一个分部类时,您应该为生成的类创建自己的扩展,如“myWebservice_partial.cs”,将该类重命名为:
- 公共部分类“GENERATEDCLASSNAME”{}
并定义/重写构造函数。您可以在其中设置UserAgent。这是updatesave
这段代码没有经过测试,是从我的脑子里写出来的。我现在不知道你是否必须从SoapHttpClientProtocol进行innerhit(见评论)
例如
文件名:WsClass_partial.cs
public partial class WsClass /* :SoapHttpClientProtocol */ {
public WsClass(string useragent):this(){
this.UserAgent = useragent;
}
}
生成的Web服务引用类本身派生自SoapHttpClientProtocol,如下所示:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Web.Services.WebServiceBindingAttribute(Name="MyGeneratedWebServiceSoap", Namespace="http://www.killroy.com/webservices/")]
public partial class MyGeneratedWebService : System.Web.Services.Protocols.SoapHttpClientProtocol
{
...
}
SoapHttpClientProtocol有一个读/写UserAgent属性,因此您可以再次从该类派生并像这样自定义用户代理(这样您可以自动用新类替换原始类的所有实例创建):
我可能忽略了一些东西,但是SoapHttpClientProtocol有一个读/写UserAgent属性:@SimonMourier抱歉,我没有解释清楚为什么我没有这么做。问题现在更新了为什么在实例化WebService生成的类时不能更改属性,而不对生成的代码进行任何更改?您也可以从类中派生。@SimonMourier我还想避免每次实例化(DRY等)时都必须指定UA字符串,但派生是一个好主意,可以工作-子类可以将UA写入构造函数,最后一个解决方案是使用反射攻击HttpWebClientProtocol,并在任何web服务实例化之前更改默认的用户代理字符串。这当然不受支持:typeof(HttpWebClientProtocol).GetField(“UserAgentDefault”,bindingsflags.Static | bindingsflags.NonPublic).SetValue(null,“我的用户代理”)代码>
public class SuperWs: MyGeneratedWebService
{
public SuperWs()
{
UserAgent = "Mozilla/5.0 (Killroy was here)";
}
}