web-dev-qa-db-fra.com

Comment POST XML dans le contrôleur MVC? (au lieu de clé/valeur)

En utilisant Fiddler, je peux passer dans le corps

someXml = ThisShouldBeXml

puis dans le contrôleur

    [HttpPost]
    public ActionResult Test(object someXml)
    {
        return Json(someXml);
    }

obtient ces données sous forme de chaîne

Comment faire en sorte que fiddler passe le code XML à ActionController de MVC? Si j'essaie de définir la valeur dans le corps en tant que fichier XML brut, cela ne fonctionne pas.

Et pour les points bonus, comment puis-je utiliser VBScript/ASP classique?

J'ai actuellement

DataToSend = "name=JohnSmith"

          Dim xml
         Set xml = server.Createobject("MSXML2.ServerXMLHTTP")
   xml.Open "POST", _
             "http://localhost:1303/Home/Test", _
             False
 xml.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
 xml.send DataToSend
18
punkouter2018

Vous ne pouvez pas transmettre directement des données XML sous forme de fichier au contrôleur MVC. Une des meilleures méthodes consiste à transmettre des données XML en tant que flux avec publication HTTP.

Pour poster du XML,

  1. Convertir les données XML en un flux et liées à un en-tête HTTP
  2. Définissez le type de contenu sur "text/xml; encoding = 'utf-8'"

Référez-vous à this stackoverflow post pour plus de détails sur la publication de XML sur MVC Controller

Pour récupérer le code XML dans le contrôleur, utilisez la méthode suivante

[HttpPost] 
public ActionResult Index()
{
    HttpWebResponse response = (HttpWebResponse)request.GetResponse();

    if (response.StatusCode == HttpStatusCode.OK)
    {
        // as XML: deserialize into your own object or parse as you wish
        var responseXml = XDocument.Load(response.GetResponseStream());

        //in responseXml variable you will get the XML data
    }
}
9
Adersh M

Cela semble être le moyen de payer XML à un contrôleur MVC

Comment passer XML en tant que POST à un ActionResult dans ASP MVC .NET

J'ai essayé de faire en sorte que cela fonctionne avec l'API WEB, mais je n'ai pas pu utiliser le contrôleur MVC.

3
punkouter2018

Afin de transmettre les données sous forme de fichier dans MVC, vous devez créer votre propre outil de formatage de type de support pour gérer le texte brut. Ajoutez ensuite le formateur à la section config.

Pour utiliser le nouveau formateur, spécifiez le type de contenu pour ce formateur, par exemple, text/plain .

Exemple de formateur pour le texte

using System;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.IO;
using System.Text;

namespace SampleMVC.MediaTypeFormatters
{
    public class TextMediaTypeFormmatter : XmlMediaTypeFormatter
    {
        private const int ByteChunk = 1024;
        private UTF8Encoding StringEncoder = new UTF8Encoding();

        public TextMediaTypeFormmatter()
        {
            base.UseXmlSerializer = true;
            SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/plain"));
        }

        public override bool CanReadType(Type type)
        {
            if (type == typeof(string))
            {
                return true;
            }
            return false;
        }

        public override bool CanWriteType(Type type)
        {
            if (type == typeof(string))
            {
                return true;
            }
            return false;
        }

        public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, System.Net.Http.HttpContent content, IFormatterLogger formatterLogger)
        {
            StringBuilder StringData = new StringBuilder();
            byte[] StringBuffer = new byte[ByteChunk];
            int BytesRead = 0;

            Task<int> BytesReadTask = readStream.ReadAsync(StringBuffer, 0, ByteChunk);
            BytesReadTask.Wait();

            BytesRead = BytesReadTask.Result;
            while (BytesRead != 0)
            {
                StringData.Append(StringEncoder.GetString(StringBuffer, 0, BytesRead));
                BytesReadTask = readStream.ReadAsync(StringBuffer, 0, ByteChunk);
                BytesReadTask.Wait();

                BytesRead = BytesReadTask.Result;
            }

            return Task<object>.Run(() => BuilderToString(StringData));
        }

        private object BuilderToString(StringBuilder StringData)
        {
            return StringData.ToString();
        }

        public override Task WriteToStreamAsync(Type type, object value, Stream writeStream, System.Net.Http.HttpContent content, System.Net.TransportContext transportContext)
        {
            byte[] StringBuffer = StringEncoder.GetBytes((string)value);
            return writeStream.WriteAsync(StringBuffer, 0, StringBuffer.Length);
        }
    }
}

Méthode du contrôleur:

[HttpPost]
public async Task<HttpResponseMessage> UsingString([FromBody]string XmlAsString)
{
    if (XmlAsString == null)
    {
        return this.Request.CreateResponse(HttpStatusCode.BadRequest);
    }

    return this.Request.CreateResponse(HttpStatusCode.OK, new { });
}

Configuration dans la méthode de registre WebApiConfig.cs:

config.Formatters.Add(new TextMediaTypeFormmatter());

En-têtes de violoneux:

User-Agent: Fiddler
Content-Type: text/plain
2

MVC Controller n’est pas idéal pour ce type de traitement des demandes, mais c’était là la tâche à accomplir. Allons-y. Ayons un XML que je dois accepter:

<document>
<id>123456</id>
    <content>This is document that I posted...</content>
    <author>Michał Białecki</author>
    <links>
        <link>2345</link>
        <link>5678</link>
    </links>
</document>

J'ai essayé quelques solutions avec la désérialisation de paramètres intégrée, mais aucune ne semble fonctionner, et finalement, j'ai procédé à la désérialisation d'une requête dans un corps de méthode. J'ai créé une classe générique d'assistance pour cela:

public static class XmlHelper
{
    public static T XmlDeserializeFromString<T>(string objectData)
    {
        var serializer = new XmlSerializer(typeof(T));

        using (var reader = new StringReader(objectData))
        {
            return (T)serializer.Deserialize(reader);
        }
    }
}

J'ai décoré mon DTO avec les attributs XML:

[XmlRoot(ElementName = "document", Namespace = "")]
public class DocumentDto
{
    [XmlElement(DataType = "string", ElementName = "id")]
    public string Id { get; set; }

    [XmlElement(DataType = "string", ElementName = "content")]
    public string Content { get; set; }

    [XmlElement(DataType = "string", ElementName = "author")]
    public string Author { get; set; }

    [XmlElement(ElementName = "links")]
    public LinkDto Links { get; set; }
}

public class LinkDto
{
    [XmlElement(ElementName = "link")]
    public string[] Link { get; set; }
}

Et utilisé tout cela dans un contrôleur:

public class DocumentsController : Controller
{
    // documents/sendDocument
    [HttpPost]
    public ActionResult SendDocument()
    {
        try
        {
            var requestContent = GetRequestContentAsString();
            var document = XmlHelper.XmlDeserializeFromString<DocumentDto>(requestContent);

            return new HttpStatusCodeResult(HttpStatusCode.OK);
        }
        catch (System.Exception)
        {
            // logging
            return new HttpStatusCodeResult(HttpStatusCode.InternalServerError);
        }
    }

    private string GetRequestContentAsString()
    {
        using (var receiveStream = Request.InputStream)
        {
            using (var readStream = new StreamReader(receiveStream, Encoding.UTF8))
            {
                return readStream.ReadToEnd();
            }
        }
    }
}

Pour l'utiliser, il suffit d'envoyer une demande en utilisant par exemple Postman. J'envoie la demande POST à http://votredomaine.com/documents/sendDocument endpoint avec le corps xml mentionné ci-dessus. Un détail qui mérite d'être mentionné est un en-tête. Ajouter un type de contenu: text/xml ou une requête de travail.

Et il fonctionne:  working deserialization

Vous pouvez voir le post entier sur mon blog: http://www.michalbialecki.com/2018/04/25/accept-xml-request-in-asp-net-mvc-controller/

0
Mik