User Tag List

Resultados 1 al 11 de 11

Tema: Http según C#, y la liada de las peticiones

  1. #1

    Fecha de ingreso
    Sep 2005
    Mensajes
    15,128
    Mencionado
    245 Post(s)
    Tagged
    1 Tema(s)
    Agradecer Thanks Given 
    665
    Agradecer Thanks Received 
    1,825
    Thanked in
    Agradecido 1,250 veces en [ARG:2 UNDEFINED] posts

    Http según C#, y la liada de las peticiones

    Buenas a todos:

    Necesito que me echéis un cable, aunque sea al cuello.
    Antecedentes
    Estoy cambiando el motor de una WebApi, que antes usaba una API a través de la típica dll, con sus funciones, variables... todo muy C.
    Pero los tiempos cambian y ahora nos "obligan" a utilizar una API web, en que las peticiones se hacen mediante HTTP y comandos GET, POST o PU... PATCH.
    Los comandos más sencillos (el 80% de la API) no he tenido problemas: tengo una instancia HttpClient, que contiene los datos de logeo en el sistema, y es lo que uso, junto a JsonConvert.Serialize (para convertir clases en datos y datos en clases) para hacer mis peticiones.

    Pero ahora resulta que tengo que anexar documentos, y la API trae una función sencilla para hacerlo de forma local, y un galimatías para hacerlo de forma remota.
    Con la forma sencilla creo un objeto "attachment" en la BBDD que puedo anexar a cualquier documento, y funciona aunque la API web esté en otra máquina... pero el fichero no se copia a la carpeta donde debería guardarse de forma automática, junto a todos los anexos.

    El problema
    Según la documentación, para poder hacer el anexo correctamente, debo hacer una petición multiparte, que tenga el siguiente aspecto:
    Código:
    POST /b1s/v1/Attachments2 HTTP/1.1
    Content-Type: multipart/form-data; boundary=myBoundary
    --myBoundary
    Content-Disposition: form-data; name="files"; filename="image1.jpg"
    Content-Type: image/jpeg
    
    <image binary data>
    --myBoundary
    Content-Disposition: form-data; name="files"; filename="image2.jpg"
    Content-Type: image/jpeg
    
    <image binary data>
    --myBoundary--
    El problema es que no sé traducir todo eso a comandos de la librería .Net.Http. Todos mis intentos me han producido una respuesta 405 (Method not allowed), pero si profundizo en el error, hay un error "250: Bad post content" por ahí dentro. Lo he intentado incluso con ChatGPT, pero hasta él se lía mezclando el HttpContent con un MultipartContent.
    Soy tan inútil, que no sé qué significa "<image binary data>"... Sí, sé que es el contenido del fichero, pero no sé a qué lo tengo que convertir para ponerlo ahí, ni cómo incrustarlo.
    Lo más limpio que tengo hecho sería esto:

    Código:
    public static async Task<HttpResponseMessage> AddNetAttachmentList (HttpClient client, List<string> fileList)
            {
                HttpRequestMessage request;
                HttpResponseMessage response = null;
                MultipartFormDataContent mpContent;
                StringContent content;
                string boundary;
                string tempString;
                byte[] fileContent;
    
                        JsonSerializerSettings serializeSettings = new Newtonsoft.Json.JsonSerializerSettings()
                        {
                            NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore,
                            //DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.Ignore,
                            //Culture = new System.Globalization.CultureInfo("en-US")
                        };
    
                        //Creando petición multipart
                        boundary = "Attachments2_AddList";
                        mpContent = new MultipartFormDataContent(boundary);
    
                        for (int i = 0; i < fileList.Count; i++)
                        {
                            fileContent = File.ReadAllBytes(fileList[i]);
                            //var fileContentStream = new MemoryStream(fileContent);
                            //var fileContentStreamContent = new StreamContent(fileContentStream);
                            var fileContentStreamContent = new ByteArrayContent(fileContent);
    
                            switch (Path.GetExtension(fileList[i]))
                            {
                                case ".jpg":
                                    fileContentStreamContent.Headers.Add("Content-Type","image/jpeg");
                                    mpContent.Add(fileContentStreamContent, "files", Path.GetFileName(fileList[i]));
                                    break;
                                case ".pdf":
                                    //fileContent = File.ReadAllBytes(fileList[i]);
                                    //content = new ByteArrayContent(fileContent);
                                    //content.Headers.ContentDisposition = new ContentDispositionHeaderValue(string.Format("form-data; name=\"files\"; filename=\"{0}\"", fileList[i]));
                                    //content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
                                    break;
                                default:
                                    fileContentStreamContent.Headers.Add("Content-Type", "application/octet-stream");
                                    mpContent.Add(fileContentStreamContent, "files", Path.GetFileName(fileList[i]));
                                    break;
                            }
                        }
    
    
                        response = client.PostAsync("Attachments2", mpContent).Result;
    
                  return response;
    Obviamente he quitado mucha paja por en medio (gestión de errores, líneas de debug, etc...), y lo he intentado de un par de formas más, pero no consigo el resultado esperado.
    ¿Alguien me puede ayudar? Si no puede ser en C#, en algo que sea lo más parecido posible.

    Gracias.
    PROYECTOS REALIZADOS: FrikiMusic, Motor Scroll Tileado v3.2, Venturer2X (GP2X/WIZ), Echo, Screen Break Time
    PROYECTOS EN MARCHA (algunos): Bennu GP2X: 95% (necesito ayuda) ¡Antes de Halloween!: 92% SpaceH2H: 8%

  2. #2

    Fecha de ingreso
    Nov 2005
    Ubicación
    Excartagenero
    Mensajes
    23,568
    Mencionado
    276 Post(s)
    Tagged
    0 Tema(s)
    Agradecer Thanks Given 
    5,954
    Agradecer Thanks Received 
    5,749
    Thanked in
    Agradecido 3,748 veces en [ARG:2 UNDEFINED] posts
    Entradas de blog
    1
    Cita Iniciado por Drumpi Ver mensaje
    Content-Type: image/jpeg

    <image binary data>
    Mira en C# cómo convertir una imagen JPG a datos binarios, seguro es algo muy común y fácil de hacer.

    -----Actualizado-----

    En PHP me suena haber hecho esto algunas veces.

    Por lo que veo, primero se pone el "mime" (image/png...) y después la imagen convertida a datos base64.

    Queda algo asi: data:image/gif;base64,R0lGODlhEAAOALMAAOazToeHh0tLS/7LZv/0jvb29t/f3/..............

  3. #3

    Fecha de ingreso
    Sep 2005
    Mensajes
    15,128
    Mencionado
    245 Post(s)
    Tagged
    1 Tema(s)
    Agradecer Thanks Given 
    665
    Agradecer Thanks Received 
    1,825
    Thanked in
    Agradecido 1,250 veces en [ARG:2 UNDEFINED] posts
    A ver, es posible que el problema que tengo sea de conversión del fichero a algo que se pueda adjuntar (voy a hacer una prueba con un texto plano puesto a pelo, que de eso sí tengo ejemplo), pero lo que me preocupa, en realidad, es todo lo demás.
    Si por mi fuera, monto el primer código en una string y se lo largo al método que sea, pero no sé ni hacer eso, aparte de que estoy seguro de que es la forma más burda e incorrecta de hacer las cosas.
    Apenas he tocado programación Web, y casi nunca he hecho peticiones en red (o han sido GEt, o POST con JSON serializados, una y otra vez), y esto me supera
    PROYECTOS REALIZADOS: FrikiMusic, Motor Scroll Tileado v3.2, Venturer2X (GP2X/WIZ), Echo, Screen Break Time
    PROYECTOS EN MARCHA (algunos): Bennu GP2X: 95% (necesito ayuda) ¡Antes de Halloween!: 92% SpaceH2H: 8%

  4. #4

    Fecha de ingreso
    Nov 2005
    Ubicación
    Excartagenero
    Mensajes
    23,568
    Mencionado
    276 Post(s)
    Tagged
    0 Tema(s)
    Agradecer Thanks Given 
    5,954
    Agradecer Thanks Received 
    5,749
    Thanked in
    Agradecido 3,748 veces en [ARG:2 UNDEFINED] posts
    Entradas de blog
    1
    No me suena nunca haber usado eso de PATCH, sí lo de GET y POST.

    Yo te diría que primero te asegures que funciona la comunicación con el ejemplo mas simple posible y luego le vas agregando cosas.

    Yo de C# ni idea, de peticiones, llevo unos días haciendo cosas AJAX con Javascript, que la verdad funciona muy bien ahora sin ninguna librería extra, lo que sería "Javascript vainilla"

  5. #5

    Fecha de ingreso
    Jun 2004
    Ubicación
    Vivo en el pito foro...
    Mensajes
    20,686
    Mencionado
    70 Post(s)
    Tagged
    0 Tema(s)
    Agradecer Thanks Given 
    229
    Agradecer Thanks Received 
    742
    Thanked in
    Agradecido 466 veces en [ARG:2 UNDEFINED] posts
    Entradas de blog
    28
    Buscate otra libreria con soporte explicito de multi-parte. Meterse en estos berenjenales no merece la pena.

    EDIT: Nuevas versiones de .NET tienen soporte explicito: https://stackoverflow.com/a/18233515 o https://learn.microsoft.com/en-us/do...t?view=net-8.0 o https://makolyte.com/csharp-how-to-s...th-httpclient/
    Última edición por pakoito; 10/01/2024 a las 20:20

  6. #6

    Fecha de ingreso
    Sep 2005
    Mensajes
    15,128
    Mencionado
    245 Post(s)
    Tagged
    1 Tema(s)
    Agradecer Thanks Given 
    665
    Agradecer Thanks Received 
    1,825
    Thanked in
    Agradecido 1,250 veces en [ARG:2 UNDEFINED] posts
    Al final lo consulté al experto contratado por la empresa. Normalmente tarda días en responder, pero tenía el día tonto y nos pusimos al ajo.

    A ver, las peticiones simples las hago sin problemas, y por lo que respecta a montar una petición multiparte, no andaba demasiado lejos en una de las implementaciones que hice... y aún así, al experto no le funcionaba tampoco.
    Tras unas cuantas pruebas, "bajamos a los infiernos", y empezamos a montar la petición "a mano"... Usando las librerías .Net.Http, pero escribiendo boundaries, content-types y demás a base de cadenas de texto. Usar Postman tampoco ayudaba, porque ahí sí funcionaba.

    Tras 2 horas, el problema venía porque en la cabecera había una serie de valores que necesitaban comillas dobles, y porque los "boundaries" se estaban enviando con comillas cuando debían ir sin ellas. Y eso lo sacó porque existe una librería que (en teoría) simplifica las cosas, y leyó este problema en los comentarios del código fuente.
    Total, que si a un experto le costó eso, yo no lo hubiera sacado en la vida.

    Y todavía habrá quien pregunte que por qué no me gusta la programación web
    PROYECTOS REALIZADOS: FrikiMusic, Motor Scroll Tileado v3.2, Venturer2X (GP2X/WIZ), Echo, Screen Break Time
    PROYECTOS EN MARCHA (algunos): Bennu GP2X: 95% (necesito ayuda) ¡Antes de Halloween!: 92% SpaceH2H: 8%

  7. #7

    Fecha de ingreso
    Nov 2005
    Ubicación
    Excartagenero
    Mensajes
    23,568
    Mencionado
    276 Post(s)
    Tagged
    0 Tema(s)
    Agradecer Thanks Given 
    5,954
    Agradecer Thanks Received 
    5,749
    Thanked in
    Agradecido 3,748 veces en [ARG:2 UNDEFINED] posts
    Entradas de blog
    1
    Cita Iniciado por Drumpi Ver mensaje
    Y todavía habrá quien pregunte que por qué no me gusta la programación web
    Es que estás en el lenguaje equivocado :P

  8. #8

    Fecha de ingreso
    Sep 2005
    Mensajes
    15,128
    Mencionado
    245 Post(s)
    Tagged
    1 Tema(s)
    Agradecer Thanks Given 
    665
    Agradecer Thanks Received 
    1,825
    Thanked in
    Agradecido 1,250 veces en [ARG:2 UNDEFINED] posts
    ¿Perdona?
    ¿Me estás diciendo que, en un ecosistema, que se basa en la interpretación de comandos de texto plano, en el que puedes definir una variable que puede contener, literalmente, cualquier cosa, y que te tienes que fiar de que lo va a interpretar como el tipo que realmente quieres que sea, y que, de pronto, por un "quítame de ahí esas comillas, o te hundo", el problema está en el lenguaje que estoy usando?

    Yo me vuelvo a los infiernos del código de bajo nivel. Programar en ASM del 68K era más fácil que esto
    PROYECTOS REALIZADOS: FrikiMusic, Motor Scroll Tileado v3.2, Venturer2X (GP2X/WIZ), Echo, Screen Break Time
    PROYECTOS EN MARCHA (algunos): Bennu GP2X: 95% (necesito ayuda) ¡Antes de Halloween!: 92% SpaceH2H: 8%

  9. #9

    Fecha de ingreso
    Nov 2005
    Ubicación
    Excartagenero
    Mensajes
    23,568
    Mencionado
    276 Post(s)
    Tagged
    0 Tema(s)
    Agradecer Thanks Given 
    5,954
    Agradecer Thanks Received 
    5,749
    Thanked in
    Agradecido 3,748 veces en [ARG:2 UNDEFINED] posts
    Entradas de blog
    1
    Donde esté PHP que se quiten mierda5 modernas o de bajo nivel.

  10. #10

    Fecha de ingreso
    Sep 2005
    Mensajes
    15,128
    Mencionado
    245 Post(s)
    Tagged
    1 Tema(s)
    Agradecer Thanks Given 
    665
    Agradecer Thanks Received 
    1,825
    Thanked in
    Agradecido 1,250 veces en [ARG:2 UNDEFINED] posts
    Voy a aprovechar el hilo para hacer una consulta, y así no lleno el foro con mis neuras

    He seguido avanzando en el proyecto, y ahora resulta que, el problema que tenía con la API binaria, y que nos ha obligado a cambiar la forma de comunicarnos con el ERP, ha vuelto... pero en forma de chapa.
    Con la API, bajo ciertas circunstancias (que aún no tengo muy claras), genera una excepción que, ejecutándose dentro de IIS como una WebApi, provoca la caída de su "grupo de aplicaciones", y nos obligaba a reiniciar la web manualmente. En ocasiones, el error era tan catastrófico que incluso echaba abajo el servicio W3WP de Windows.

    Ahora, usando las peticiones web, bajo unas circunstancias similares, llega un punto en que cualquier petición que le hagamos al HttpClient nos devuelve un error 500 (InternalServerError). Lo que hacemos es que, cuando el usuario se loguea, creamos un HttpClient, y le incrustamos la cookie de autorización, y a partir de ahí lo usamos a lo largo de lo que dure su sesión (por defecto, 30 segundos, aunque para depuración lo tengo a 3 minutos). A diferencia de la otra API, si dejamos que la sesión caduque, y que el código se encargue de reconectar, o si descartamos el HttpClient y creamos otro, todo vuelve a funcionar con normalidad (y de momento, no se ha caído ni el grupo de aplicaciones ni nada).

    Sabiendo esto, había pensado hacer que, cada petición del usuario genere un HttpClient, que se use para todas las tareas que deben ejecutarse en dicha petición. Supuestamente, habrá pocos usuarios de la web, y las peticiones entrará una cada 5 a 15 minutos en lugares tranquilos, o 2 por minuto en entornos con más actividad (por ahora, sólo usamos esta API web para peticiones POST y PUT, para el GET seguimos con el sistema antiguo).
    Lo que desconozco son las consecuencias que puede acarrear esto. He leído que aunque se deje de usar el HttpClient, su puerto de comunicación sigue en uso durante unos 4 minutos, y puede provocar... no sé si he entendido que se queda sin puertos, o que se le somete a mucho estrés al sistema que los asigna.

    Por si acaso, de momento, estoy intentando detectar cuándo entra en "modo negación", y cuando pille un error 500, que desloguée al usuario y reconecte con un HttpClient "fresco". El problema es que tengo que hacer eso con cada petición (o al menos, con las más problemáticas).
    PROYECTOS REALIZADOS: FrikiMusic, Motor Scroll Tileado v3.2, Venturer2X (GP2X/WIZ), Echo, Screen Break Time
    PROYECTOS EN MARCHA (algunos): Bennu GP2X: 95% (necesito ayuda) ¡Antes de Halloween!: 92% SpaceH2H: 8%

  11. #11

    Fecha de ingreso
    Nov 2005
    Ubicación
    Excartagenero
    Mensajes
    23,568
    Mencionado
    276 Post(s)
    Tagged
    0 Tema(s)
    Agradecer Thanks Given 
    5,954
    Agradecer Thanks Received 
    5,749
    Thanked in
    Agradecido 3,748 veces en [ARG:2 UNDEFINED] posts
    Entradas de blog
    1
    Madremia las cosas que te pasan. Con razón la tasa de suicidio entre algunos desarrolladores es tan alta :P

  12. El siguiente usuario agradece a josepzin este mensaje:

    fbustamante (06/02/2024)

Etiquetas para este tema

Permisos de publicación

  • No puedes crear nuevos temas
  • No puedes responder temas
  • No puedes subir archivos adjuntos
  • No puedes editar tus mensajes
  •