Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.219.227.137] |
|
Сообщ.
#1
,
|
|
|
Создал вэб-сервис, в нём метод, возвращающий List<ACountry>,
namespace table { [XmlInclude(typeof(ACountry))] [Serializable] public abstract class ACountry { // ... плюс ещё много методов #region Fields [MapField("Id")] public abstract string m_strId { get; set; } [MapField("Name")] public abstract string m_strName { get; set; } #endregion } } [WebMethod] //[System.Xml.Serialization.XmlInclude(typeof(ACountry))] public List<ACountry> GetCountriesHavingTeams() { return ACountry.GetCountryWithTeamList(); } В отдельном приложении создал WebReference на этот WebService (под именем ElitaWS), и пытаюсь получить данные: //[XmlInclude(typeof(ElitaWS.ACountry))] private void MyMethod { ElitaWS.ws_data w = new HW.ElitaWS.ws_data(); HW.ElitaWS.Pair[] lstC = w.GetCountryFieldsHavingTeams(); } После отработки вэб-службы (смотрю пошагово отладчиком) получаю Цитата System.Web.Services.Protocols.SoapException was unhandled by user code Message="System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.InvalidOperationException: There was an error generating the XML document. ---> System.InvalidOperationException: The type table.BLToolkitExtension.ACountry was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically.\n at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriter1.Write2_ACountry(String n, String ns, ACountry o, Boolean isNullable, Boolean needType)\n at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriter1.Write6_Item(Object[] p)\n at Microsoft.Xml.Serialization.GeneratedAssembly.ArrayOfObjectSerializer5.Serialize(Object objectToSerialize, XmlSerializationWriter writer)\n at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id)\n --- End of inner exception stack trace ---\n at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id)\n at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle)\n at System.Web.Services.Protocols.SoapServerProtocol.WriteReturns(Object[] returnValues, Stream outputStream)\n at System.Web.Services.Protocols.WebServiceHandler.WriteReturns(Object[] returnValues)\n at System.Web.Services.Protocols.WebServiceHandler.Invoke()\n --- End of inner exception stack trace ---" Source="System.Web.Services" Actor="" Lang="" Node="" Role="" StackTrace: at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall) at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters) at HW.ElitaWS.ws_data.GetCountriesHavingTeams() in d:\project\tests\hw\web references\elitaws\reference.cs:line 121 at HW.WorkflowHW.InWorkingHours(Object sender, ConditionalEventArgs e) in D:\Project\Tests\HW\Workflow1.cs:line 35 at System.Workflow.Activities.CodeCondition.Evaluate(Activity ownerActivity, IServiceProvider provider) at System.Workflow.Activities.IfElseActivity.Execute(ActivityExecutionContext executionContext) at System.Workflow.ComponentModel.ActivityExecutor`1.Execute(T activity, ActivityExecutionContext executionContext) at System.Workflow.ComponentModel.CompositeActivityExecutor`1.Execute(T activity, ActivityExecutionContext executionContext) at System.Workflow.ComponentModel.ActivityExecutor`1.Execute(Activity activity, ActivityExecutionContext executionContext) at System.Workflow.ComponentModel.ActivityExecutionFilter.Execute(Activity activity, ActivityExecutionContext executionContext) at System.Workflow.ComponentModel.FaultAndCancellationHandlingFilter.Execute(Activity activity, ActivityExecutionContext executionContext) at System.Workflow.ComponentModel.ActivityExecutorOperation.Run(IWorkflowCoreRuntime workflowCoreRuntime) InnerException: Как я понимаю, куда-то надо добавить атрибут XmlInclude, куда толком - не понял, пытался маны найти - не получилось. Пробовал добавлять атрибут "везде, где только можно" - тоже безрезультатно. Хэлп, плиз. Добавлено Добавил только что [Serializable] к классу ACountry - не помогло. P.S. Обычные типы (Pair, string, List<Pair>) - передаются без проблем. |
Сообщ.
#2
,
|
|
|
Я не знаю тонкостей в данном вопросе, но когда я юзал WCF и передавал через него типизированные коллекции (в т.ч. деревья) никаких проблем не возникало, и всё работало правильно.
|
Сообщ.
#3
,
|
|
|
А как у тебя были объявлены передаваемые типы? [Serializable]? Что-то ещё?
|
Сообщ.
#4
,
|
|
|
Для дерева у меня был свой тип. он был настраеваемый (то бишь с дженериками, <T>)+ Serializable (точнее ISerializable).
Добавлено Стоп! ща глянул код - я соврал. У меня тогда возникли какие то проблемы, и потому сериализовал код я вручнуй, а сервис передавал просто массив байт. |
Сообщ.
#5
,
|
|
|
Alexus во... и я думаю, что у меня проблемы с сериализацией... скорее всего чистой декларации атрибутом [Serializable] - мало... надо ещё чё-нить добавить. Надо почитать про сериализацию
Цитата Alexus @ передавал просто массив байт ага, вот и я извращался так же, но я передавал List<Pair> |
Сообщ.
#6
,
|
|
|
Я думаю, что все нормально будет передаваться, если поступить так:
public CountryList GetCountriesHavingTeams() { return ACountry.GetCountryWithTeamList(); } где СountryList определен так: [Serializable] public class CountryList : List<Country> { } |
Сообщ.
#7
,
|
|
|
Цитата juice @ public class CountryList : List<Country> { } - juice прав, у дженериков траблы с сериализацией, надо обертки писать |
Сообщ.
#8
,
|
|
|
PIL
juice Спасибо, вечером попробую - доложу. |
Сообщ.
#9
,
|
|
|
Не. Сериализуется моё дерево нормально обычным форматтером (BinaryFormatter) - .Serialize(), .Deserealize() без каких либо модификаций.
Но вот если сериализовать объекты начинает инфраструктура WCF(а не я через форматтер), возникают проблемы. Видать фишка в том, что WCF юзает BinaryFormatter как то не стандартно... Я думаю, при использовании WCF нужно действительно юзать какие то дополнительные аттрибуты, управляющие тем как WCF использует стандартные механизмы сериализации. Но я не стал копать глубоко - мне хватило просто того, что почти всё передаётся нормально, о довольно сложные вещи можно и передать в виде масива байт... |
Сообщ.
#10
,
|
|
|
К слову, я доступался к вэб-сервису из WWF-проекта.
|
Сообщ.
#11
,
|
|
|
Цитата Alexus @ Не. Сериализуется моё дерево нормально обычным форматтером (BinaryFormatter) - .Serialize(), .Deserealize() без каких либо модификаций. Но вот если сериализовать объекты начинает инфраструктура WCF(а не я через форматтер), возникают проблемы. ПРоблемы возникали такие - на сервере метод отрабатывает, а клиент результата не получает - вместо этого ошибка The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was '00:00:59.9843750'. Как видно, причины совсем не очевидны. Однако с трблой я разобрался: она возникает в том случае, если в контракте указан какой то базовый тип или интерфейс, а фактически передаётся его наследдник. В общем, если в "serialization graph" появляется объект неожиданного типа. Та же трабла есть при XML сериализации - и решается она здесь так же - аттрибутом [ServiceKnownType(...)] |
Сообщ.
#12
,
|
|
|
Цитата Alexus @ она возникает в том случае, если в контракте указан какой то базовый тип или интерфейс, а фактически передаётся его наследдник. В общем, если в "serialization graph" появляется объект неожиданного типа. Та же трабла есть при XML сериализации - и решается она здесь так же - аттрибутом [ServiceKnownType(...)] - для WCF - есть очень красивый выход: использование NetDataContractSerializer на клиенте и на сервере, тогда можно хоть интерфейсные ссылки, хоть женерики, все передавать. Он умеет сериализовать-десериализовать информацию о типах. Но как его применять - это наверное надо в FAQ писать, либо статью, там с десяток классов писать нужно для удобства юзания. |
Сообщ.
#13
,
|
|
|
да, заморочек там предостаточно. Но цель их введения проста - обеспечить возможность клиенту работать со службой, не получая от неё никаких сборок с типами, следуя, вместо этого, опубликованному контракту на вызовы и, главное, на данные.
Добавлено И если чётко понимать и разграничивать какие форматы данных подлежат передаче в виде контракта, а какаие - в виде сераиализованных объектов, тогда проблемы исчезают. А отличие между ними в том, что в контрактных данных запрещён полиморфизм, а в сериализованных - разрешён. |