Как установить заголовок User-Agent в SoapHttpClientProtocol?
Я звоню стороннему SOAP-сервису (интернет-магазин Magento) в ASP.NET MVC4. При импорте ссылки на веб-службу все методы службы автоматически реализуются Visual Studio, например, метод мыла входа в систему реализуется как
public string login(string username, string apiKey) {
object[] results = this.Invoke("login", new object[] {
username,
apiKey});
return ((string)(results[0]));
}
Но когда я вызываю этот метод, this.Invoke
отправляет POST с автоматически добавленным заголовком пользовательского агента:
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0;
MS Web Services Client Protocol 4.0.30319.18444)
Этот заголовок сообщает третьей стороне, что пользовательским агентом является IE6. И многие сайты автоматически блокируют IE6 с сообщением, в котором говорится что-то вроде "Мы не поддерживаем IE6. Получите настоящий браузер и попробуйте снова"
Поэтому мыльный вызов прерывается, но только потому, что сторонний сайт считает, что мы используем IE6, а не потому, что с мыльным вызовом что-то не так. Если бы мы могли изменить этот заголовок, чтобы имитировать строку UA современного веб-браузера, такой проблемы не было бы.
Так как же изменить строку UA, используемую при вызове метода SoapHttpClientProtocol? Все это происходит внутри this.Invoke
метод, который является частью ядра.NET.
РЕДАКТИРОВАТЬ:
Предмет 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"
здесь должно быть более полезное решение.
2 ответа
Сгенерированный ссылочный класс веб-службы происходит от 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 для чтения / записи, поэтому вы можете снова извлечь из этого класса и настроить пользовательский агент следующим образом (таким образом вы можете автоматически заменить все создания экземпляров исходного класса новым):
public class SuperWs: MyGeneratedWebService
{
public SuperWs()
{
UserAgent = "Mozilla/5.0 (Killroy was here)";
}
}
Является ли автоматически сгенерированный класс частичным классом?
Если это частичный класс, то вы должны создать собственное расширение для сгенерированного класса, например "myWebservice_partial.cs", переименовать класс в:
открытый частичный класс "GENERATEDCLASSNAME"{}
и определить / переопределить конструктор. в этом вы можете установить свой UserAgent. Это обновления.
Этот код не проверен и написан из моего мозга. Сейчас я не знаю, нужно ли вам подключаться к нему из SoapHttpClientProtocol (см. Комментарий)
НАПРИМЕР
Имя файла: WsClass_partial.cs
public partial class WsClass /* :SoapHttpClientProtocol */ {
public WsClass(string useragent):this(){
this.UserAgent = useragent;
}
}