Изменить XML-запрос на мыло перед отправкой

Я новичок в этом мыльном сообщении и прочем, у меня возникли некоторые проблемы с использованием WebService, я создал класс с использованием WSDL.exe, первая проблема, с которой я столкнулся при выполнении команды, это создание параметра с помощью var[][] который мне пришлось заменить на одну переменную [] (массив).

Тогда он успешно компилировался, теперь у меня возникли некоторые проблемы, и я понятия не имею, как это исправить:

Запрос, который я отправляю, таков:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <soap:Body>
        <emitirWS xmlns="http://neon.stoconsulting.com/NeonEmisionWS/NeonEmisionWS?wsdl">
            <comprobante serie="W" folio="143" formaPago="01" condicionesDePago="CONTADO" tipoCambio="1.000000" moneda="MXN" metodoPago="PUE" lugarExpedicion="54080" tipoComprobante="I" subTotal="827.586207" descuento="0.000000" total="960.00" documentoErp="143" usoCfdi="G03" tipoDocumento="1">
                <envioCfdi enviarXml="1" enviarPdf="1" enviarZip="0" emails="felipe.pinav@gmail.com" />
                <emisor rfc="ASM160607Q43" nombre="ARTHUR AND SONS MEXICO" regimenFiscal="601" idEmisorSto="1" idEmisorErp="1" />
                <sucursal rfc="ASM160607Q43" nombre="Plaza Polanco" regimenFiscal="601" idEmisorSto="2" idEmisorErp="2" numeroExterior="411" calle="Avenida Palmas" colonia="Miguel Hidalgo" referencia="" municipio="Toluca" estado="Edo. de México" pais="Mexico" codigoPostal="54080" email="hola@arthursons.com" idTipoEmisor="2" idEmisorPadre="1" estatusRegistro="1" />
                <receptor rfc="PIVF810724LW9" nombre="Felipe Pina Vera" regimenFiscal="622" usoCfdi="G01" idReceptoSto="1" idReceptorErp="1" numeroExterior="141A" calle="Viveros de Coyoacán" colonia="Viveros de la Loma" municipio="Tlalnepantla" estado="Edo. de México" pais="Mexico" codigoPostal="54080" email="felipe.pinav@gmail.com" idEmisorPadre="0" estatusRegistro="1" />
                <conceptos claveProdServ="42142901" cantidad="1.000000" claveUnidad="H87" unidad="Pieza" numIdentificacion="5" descripcion="BENSEN - AZUL" valorUnitario="827.586207" importe="827.586207" descuento="0.000000" xmlns="">
                    <impuestos>
                        <trasladados base="827.586207" impuesto="002" tipoFactor="Tasa" tasaOCuota="0.160000" importe="132.413793" />
                    </impuestos>
                </conceptos>
                <impuestos totalImpuestosRetenidos="0.000000" totalImpuestosTrasladados="132.413793" xmlns="">
                    <trasladados impuesto="002" tipoFactor="Tasa" tasaOCuota="0.160000" importe="132.413793" />
                </impuestos>
            </comprobante>
        </emitirWS>
    </soap:Body>
</soap:Envelope>

Когда он достигает сервера, он не может быть обработан, так как запрос не имеет правильного формата, правильный формат:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:neon="http://neon.stoconsulting.com/NeonEmisionWS/NeonEmisionWS?wsdl">
    <soap:Body>
        <neon:emitirWS>
            <comprobante serie="W" folio="143" formaPago="01" condicionesDePago="CONTADO" tipoCambio="1.000000" moneda="MXN" metodoPago="PUE" lugarExpedicion="54080" tipoComprobante="I" subTotal="827.586207" descuento="0.000000" total="960.00" documentoErp="143" usoCfdi="G03" tipoDocumento="1">
                <envioCfdi enviarXml="1" enviarPdf="1" enviarZip="0" emails="felipe.pinav@gmail.com" />
                <emisor rfc="ASM160607Q43" nombre="ARTHUR AND SONS MEXICO" regimenFiscal="601" idEmisorSto="1" idEmisorErp="1" />
                <sucursal rfc="ASM160607Q43" nombre="Plaza Polanco" regimenFiscal="601" idEmisorSto="2" idEmisorErp="2" numeroExterior="411" calle="Avenida Palmas" colonia="Miguel Hidalgo" referencia="" municipio="Toluca" estado="Edo. de México" pais="Mexico" codigoPostal="54080" email="hola@arthursons.com" idTipoEmisor="2" idEmisorPadre="1" estatusRegistro="1" />
                <receptor rfc="PIVF810724LW9" nombre="Felipe Pina Vera" regimenFiscal="622" usoCfdi="G01" idReceptoSto="1" idReceptorErp="1" numeroExterior="141A" calle="Viveros de Coyoacán" colonia="Viveros de la Loma" municipio="Tlalnepantla" estado="Edo. de México" pais="Mexico" codigoPostal="54080" email="felipe.pinav@gmail.com" idEmisorPadre="0" estatusRegistro="1" />
                <conceptos claveProdServ="42142901" cantidad="1.000000" claveUnidad="H87" unidad="Pieza" numIdentificacion="5" descripcion="BENSEN - AZUL" valorUnitario="827.586207" importe="827.586207" descuento="0.000000">
                    <impuestos>
                        <trasladados base="827.586207" impuesto="002" tipoFactor="Tasa" tasaOCuota="0.160000" importe="132.413793" />
                    </impuestos>
                </conceptos>
                <impuestos totalImpuestosRetenidos="0.000000" totalImpuestosTrasladados="132.413793">
                    <trasladados impuesto="002" tipoFactor="Tasa" tasaOCuota="0.160000" importe="132.413793" />
                </impuestos>
            </comprobante>
        </neon:emitirWS>
    </soap:Body>
</soap:Envelope>

Мне нужно переключиться:

1) в узле конверта мне нужно добавить новый атрибут:

xmlns:neon="http://neon.stoconsulting.com/NeonEmisionWS/NeonEmisionWS?wsdl"

2) на узле emitir, мне нужно, чтобы он был <neon:emitir></neon:emitir> вместо обычного <emitir>

Когда я делаю это, все работает как шарм, как я сказал, что создал класс с помощью инструмента wsdl.exe, это код, который я использую:

 [System.Web.Services.Protocols.SoapDocumentMethodAttribute("", RequestNamespace = "http://neon.stoconsulting.com/NeonEmisionWS/NeonEmisionWS?wsdl", ResponseNamespace = "http://neon.stoconsulting.com/NeonEmisionWS/NeonEmisionWS?wsdl", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
        [return: System.Xml.Serialization.XmlElementAttribute("RespuestaWS", Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
        [WebServiceSOAPExtension]
        public respuestaWS emitirWS(comprobante comprobante)
        {
            object[] results = this.Invoke("emitirWS", new object[] {
                    comprobante});
            return ((respuestaWS)(results[0]));
        }

Спасибо, я понятия не имею, с чего начать.

1 ответ

Ну, для всех парней, которые пытаются сделать что-то подобное, и вы понятия не имеете, я закончил делать некоторые неприятные вещи, которые я не рекомендую, однако, если вы застряли как я, и у вас нет понятия, с чего начать чтобы сделать это "правильно", ну, вы можете сделать это:

Во-первых, вам нужно создать класс, который расширяет SoapExtension Как этот:

namespace SoapExentender
{
    class WebServiceSOAPExtension : SoapExtension
    {
        Stream oldStream;
        Stream newStream;
        string filename;

    public override Stream ChainStream(Stream stream)
    {
        oldStream = stream;
        newStream = new MemoryStream();
        return newStream;
    }

    // When the SOAP extension is accessed for the first time, the XML Web service method it is applied to is accessed to store the file name passed in,

    //using the corresponding SoapExtensionAttribute.    
    public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
    {
        return null;
    }

    // The SOAP extension was configured to run using a configuration file instead of an attribute applied to a specific XML Web service method.
    public override object GetInitializer(Type WebServiceType)
    {
        return null;
    }

    // Receive the file name stored by GetInitializer and store it in a member variable for this specific instance.
    public override void Initialize(object initializer)
    {
        filename = ConfigurationManager.AppSettings["STOFacturacionDLL"].ToString();
    }

    //  If the SoapMessageStage is such that the SoapRequest or SoapResponse is still in the SOAP format to be sent or received, save it out to a file.
    public override void ProcessMessage(SoapMessage message)
    {
        switch (message.Stage)
        {
            case SoapMessageStage.BeforeSerialize:
                break;
            case SoapMessageStage.AfterSerialize: //el xml serializado de salida
                WriteOutput((SoapClientMessage)message);
                break;
            case SoapMessageStage.BeforeDeserialize:
                WriteInput((SoapClientMessage)message);
                break;
            case SoapMessageStage.AfterDeserialize:
                break;
            default:
                throw new Exception("Stage inválido");
        }
    }

    // Write the contents of the outgoing SOAP message to the log file.
    public void WriteOutput(SoapClientMessage message)
    {
        newStream.Position = 0;
        FileStream fs = new FileStream(filename, FileMode.Append, FileAccess.Write);
        StreamWriter myStreamWriter = new StreamWriter(fs);
        myStreamWriter.WriteLine("================================== Fecha del request: " + DateTime.Now);
        // Print to the log file the request header field for SoapAction header.
        myStreamWriter.WriteLine(@"La acción SOAP del 'header' Http request  es: " + message.Action);

        // Print to the log file the method invoked by the client.
        myStreamWriter.WriteLine("El metodo llamado fue: " + message.MethodInfo.Name);

        // Print to the log file if the method invoked is OneWay.
        if (message.OneWay)
            myStreamWriter.WriteLine("El cliente no espera a que se termine el proceso (no es de un solo sentido)");
        else
            myStreamWriter.WriteLine("El cliente espera a que se termine el proceso");

        // Print to the log file the URL of the site that provides implementation of the method.
        myStreamWriter.WriteLine("La URL solicitada fue: " + message.Url);
        myStreamWriter.WriteLine("el contenido del request/response del ---- <soap:envelope> ---- es : ");
        myStreamWriter.Flush();

        Copy(newStream, fs);
        myStreamWriter.Close();
        //replace custom text
        string stringRequest = "";
        try
        {
            newStream.Position = 0;
            MemoryStream RequestStream = new MemoryStream();
            Copy(newStream, RequestStream);
            RequestStream.Position = 0;
            byte[] bytesRequestStream = ReadFully(RequestStream);
            stringRequest = System.Text.Encoding.UTF8.GetString(bytesRequestStream);
            stringRequest = replaceText(stringRequest, "<ReimprimirReferencia", "<thepanch:ReimprimirReferencia");
            int i = 0;
        }
        catch (Exception exc) { }

        newStream.Position = 0;
        //replace the original stream, with the custom stream
        Copy(ConvertStringToStream(stringRequest), oldStream);
    }

    private string replaceText(string MainString, string SearchString, string ReplaceWith)
    {
        MainString = MainString.Replace(SearchString, ReplaceWith);
        return MainString;
    }

    private MemoryStream ConvertStringToStream(string RequestString)
    {
        byte[] byteArray = Encoding.UTF8.GetBytes(RequestString);
        MemoryStream stream = new MemoryStream(byteArray);
        stream.Position = 0;
        return stream;
    }

    private byte[] ReadFully(Stream input)
    {
        using (MemoryStream ms = new MemoryStream())
        {
            input.CopyTo(ms);
            return ms.ToArray();
        }
    }

    public void WriteInput(SoapMessage message)
    {
        Copy(oldStream, newStream);
        FileStream fs = new FileStream(filename, FileMode.Append, FileAccess.Write);
        StreamWriter w = new StreamWriter(fs);
        string soapString = (message is SoapServerMessage) ? "SoapRequest" : "SoapResponse";
        w.WriteLine("----------" + soapString + " at " + DateTime.Now);
        w.Flush();
        newStream.Position = 0;
        Copy(newStream, fs);
        w.Close();
        newStream.Position = 0;
    }

    void Copy(Stream from, Stream to)
    {
        TextReader reader = new StreamReader(from);
        TextWriter writer = new StreamWriter(to);
        writer.WriteLine(reader.ReadToEnd());
        writer.Flush();
    }
}

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class WebServiceSOAPExtensionAttribute : SoapExtensionAttribute
{
    private int priority;

    public override Type ExtensionType
    {
        get { return typeof(WebServiceSOAPExtension); }
    }

    public override int Priority
    {
        get { return priority; }
        set { priority = value; }
    }
}

}

А затем используйте пользовательский атрибут в методе прокси-сервера для замены фактического потока на ваш пользовательский поток, метод writeOutput предназначен для "запроса", а метод writeInput для "ответа", затем вам нужно поиграть со строками, чтобы соответствовать ваши потребности, я надеюсь, это поможет.

Как я упоминал в первых строках, это не правильный путь, однако, если вы похожи на меня, не зная, с чего начать, вы можете написать свою собственную строку XML.

Другие вопросы по тегам