Re[3]: WSDL генерит неправильный SoapAction
От: Михаил Романов Удмуртия https://mihailromanov.wordpress.com/
Дата: 22.09.17 12:20
Оценка: 190 (8)
Здравствуйте, mDmitriy, Вы писали:

МР>>- на ходу правит WSDL

D>это не подходит
"На ходу" я имел ввиду "перед тем как скормить генератору"

МР>>- слегка подправить генератор (там есть несколько вариантов).

D>вот это интересно, а как?
Ну выглядит примерно так...
1. За вычитывание WSDL отвечает класс WsdlImporter. Он по сути берет на вход MetadataSet (можно получить непосредственно от сервиса или считать из локального файла), а на выходе выдает ContractDescription.

2. После того как вы получили описание контрактов, вы берете класс ServiceContractGenerator, скармливаете ему на вход эти контракты (и прочие настройки), а он вам возвращает CodeDOM для сгенерированного класса, которые можно будет через CodeDomProvider сохранить на нужном вам языке.

Через этот класс работают и svcutil и Service Reference в VS.
Соответственно, первый метод — написать свою утилиту, которая будет проходить путь до готового CodeDOM а затем его модифицировать.

Второй метод, это написать плагины для WsdlImporter и ServiceContractGenerator, это соответственно
IWsdlImportExtension — он отрабатывает в момент преобразования WSDL/XSD в описание контракта
IOperationContractGenerationExtension и IServiceContractGenerationExtension — они, понятное дело, будут вызываться при генерации соответствующих фрагментов CodeDOM.

Плагины хороши тем, что их теоретически можно подключить к тем же VS и svcutil, просто указав где-то в настройках, но зато им доступен не весь CodeDOM (вроде бы)

Есть небольшая вводная статья (помимо MSDN) WCF Extensibility – WSDL Import (and Code Generation) Extensions

D>я бы с удовольствием убрал бы из сгенерированных классов кучу всякой фигни

Я тут не уверен — возня с CodeDOM то еще удовольствие... Но небольшие правки вполне можно попытаться сделать.

D>могу прислать всю, но только вам лично, если скажете емейл

D>это конфиденциальная информация, увы
Получил, попробую посмотреть.

D>вроде даже можно такой собрать из микрософтовских классов, но тоже не знаю как

Я выше описал примерно процесс, дальше по ссылка вроде должно быть более-менее понятно, но на всякий случай приложу свой пример

  Генератор, который создает прокси-класс, который "давит" все исключения
        public void GenerateProxy()
        {
            var metadataAddress = "http://localhost:54107/CalculatorService.svc?wsdl";

            // 01. Read metadata
            MetadataExchangeClient metaClient = new MetadataExchangeClient(
                new Uri(metadataAddress), MetadataExchangeClientMode.HttpGet);
            MetadataSet metadataSet = metaClient.GetMetadata();

            // 02. Import contracts
            WsdlImporter importer = new WsdlImporter(metadataSet);

            // 03. Put contracts to generator
            ServiceContractGenerator generator = new ServiceContractGenerator();
            foreach (ContractDescription cd in importer.ImportAllContracts())
            {
                generator.GenerateServiceContractType(cd);
            }

            // 04/ Enumerates all namesapces 
            foreach (CodeNamespace nm in generator.TargetCompileUnit.Namespaces)
            {
                // Select types witch names start from "System.ServiceModel.ClientBase" (all generated classses)
                // It's small hack, becouse real names start from "System.ServiceModel.ClientBase`1"
                var types =
                     nm.Types.OfType<CodeTypeDeclaration>().Where(
                        type => type.BaseTypes.OfType<CodeTypeReference>().Any(
                            t => t.BaseType.StartsWith("System.ServiceModel.ClientBase"))).Select(t => t);

                // Enumerates all clients
                foreach (CodeTypeDeclaration type in types)
                {
                    // Select regular (not constructor) methods
                    foreach (CodeMemberMethod method in
                        type.Members.OfType<CodeMemberMethod>().Where(t => t.GetType() == typeof(CodeMemberMethod)))
                    {
                        // Create new method body
                        CodeStatementCollection code = new CodeStatementCollection();

                        // Create catch for try/catch (catch CommunicationException)
                        CodeCatchClause ctch = new CodeCatchClause(
                            "e",
                            new CodeTypeReference(typeof(CommunicationException)));

                        // Create full code: 
                        // try 
                        // { old method body } 
                        // catch(CommunicationException) {}
                        code.Add(new CodeTryCatchFinallyStatement(
                            method.Statements.OfType<CodeStatement>().ToArray(),
                            new CodeCatchClause[] { ctch }));

                        // Clear old method body and insert new
                        method.Statements.Clear();
                        method.Statements.AddRange(code);
                    }
                }
            }

            // Create С# code generator
            CodeDomProvider codeProvider = CodeDomProvider.CreateProvider("C#");
            // Create special TextWriter (with text indentation)
            IndentedTextWriter textWriter = new IndentedTextWriter(new System.IO.StreamWriter("proxy.cs"));

            CodeGeneratorOptions options = new CodeGeneratorOptions();
            options.BlankLinesBetweenMembers = true;

            // Write the code
            codeProvider.GenerateCodeFromCompileUnit(generator.TargetCompileUnit, textWriter, options);
            textWriter.Close();
        }
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.