[asp.net] 컨트롤러의 액션에서 XML을 ActionResult로 반환 하시겠습니까?

ASP.NET MVC의 컨트롤러 작업에서 XML을 반환하는 가장 좋은 방법은 무엇입니까? JSON을 반환하는 좋은 방법이 있지만 XML은 아닙니다. 실제로 XML을 View를 통해 라우팅해야합니까, 아니면 최선의 방법으로 Response를 작성해야합니까?



답변

MVCContrib 의 XmlResult 조치를 사용하십시오 .

여기에 그들의 코드가 있습니다 :

public class XmlResult : ActionResult
{
    private object objectToSerialize;

    /// <summary>
    /// Initializes a new instance of the <see cref="XmlResult"/> class.
    /// </summary>
    /// <param name="objectToSerialize">The object to serialize to XML.</param>
    public XmlResult(object objectToSerialize)
    {
        this.objectToSerialize = objectToSerialize;
    }

    /// <summary>
    /// Gets the object to be serialized to XML.
    /// </summary>
    public object ObjectToSerialize
    {
        get { return this.objectToSerialize; }
    }

    /// <summary>
    /// Serialises the object that was passed into the constructor to XML and writes the corresponding XML to the result stream.
    /// </summary>
    /// <param name="context">The controller context for the current request.</param>
    public override void ExecuteResult(ControllerContext context)
    {
        if (this.objectToSerialize != null)
        {
            context.HttpContext.Response.Clear();
            var xs = new System.Xml.Serialization.XmlSerializer(this.objectToSerialize.GetType());
            context.HttpContext.Response.ContentType = "text/xml";
            xs.Serialize(context.HttpContext.Response.Output, this.objectToSerialize);
        }
    }
}

답변

return this.Content(xmlString, "text/xml");


답변

뛰어난 Linq-to-XML 프레임 워크를 사용하여 XML을 작성하는 경우이 방법이 도움이 될 것입니다.

XDocument액션 메소드를 작성합니다 .

public ActionResult MyXmlAction()
{
    // Create your own XDocument according to your requirements
    var xml = new XDocument(
        new XElement("root",
            new XAttribute("version", "2.0"),
            new XElement("child", "Hello World!")));

    return new XmlActionResult(xml);
}

이 재사용 가능한 사용자 정의 ActionResult는 XML을 직렬화합니다.

public sealed class XmlActionResult : ActionResult
{
    private readonly XDocument _document;

    public Formatting Formatting { get; set; }
    public string MimeType { get; set; }

    public XmlActionResult(XDocument document)
    {
        if (document == null)
            throw new ArgumentNullException("document");

        _document = document;

        // Default values
        MimeType = "text/xml";
        Formatting = Formatting.None;
    }

    public override void ExecuteResult(ControllerContext context)
    {
        context.HttpContext.Response.Clear();
        context.HttpContext.Response.ContentType = MimeType;

        using (var writer = new XmlTextWriter(context.HttpContext.Response.OutputStream, Encoding.UTF8) { Formatting = Formatting })
            _document.WriteTo(writer);
    }
}

MIME 유형 (예 application/rss+xml:)과 필요한 경우 출력을 들여 쓸지 여부를 지정할 수 있습니다 . 두 속성 모두 합리적인 기본값을 가지고 있습니다.

UTF8 이외의 인코딩이 필요한 경우 해당 속성을 추가하는 것도 간단합니다.


답변

요청을 통해서만 XML을 반환하고 xml “청크”가있는 경우 컨트롤러에서 작업으로 수행 할 수 있습니다.

public string Xml()
{
    Response.ContentType = "text/xml";
    return yourXmlChunk;
}


답변

MVC Contrib에는 XmlResult (및 그 이상)가 있습니다. http://www.codeplex.com/MVCContrib보십시오


답변

최근에 Sitecore 항목 및 해당 하위 항목에서 XmlDocument를 작성하고 컨트롤러 ActionResult에서 파일로이를 리턴하는 메소드를 사용하는 Sitecore 프로젝트에 대해이 작업을 수행해야했습니다. 내 해결책 :

public virtual ActionResult ReturnXml()
{
    return File(Encoding.UTF8.GetBytes(GenerateXmlFeed().OuterXml), "text/xml");
}


답변

마지막 으로이 작업을 수행하고 다른 사람들이 고통을 덜기 위해 어떻게 여기에 문서화 할 것이라고 생각했습니다.

환경

  • VS2012
  • SQL Server 2008R2
  • .NET 4.5
  • ASP.NET MVC4 (레이저)
  • 윈도우 7

지원되는 웹 브라우저

  • 파이어 폭스 23
  • IE 10
  • 크롬 29
  • 오페라 16
  • Safari 5.1.7 (Windows 용 마지막 것)

내 작업은 ui 버튼 클릭으로 내 컨트롤러에서 메소드를 호출하고 (매개 변수 포함) xslt 변환을 통해 MS-Excel XML을 반환하도록합니다. 반환 된 MS-Excel XML은 브라우저가 열기 / 저장 대화 상자를 팝업하게합니다. 이것은 위에 나열된 모든 브라우저에서 작동해야했습니다.

처음에는 Ajax로 파일 이름에 대한 “다운로드”속성을 가진 동적 앵커를 만들려고 시도했지만 IE 또는 Safari가 아닌 5 개의 브라우저 (FF, Chrome, Opera) 중 약 3 개에서만 작동했습니다. 그리고 앵커의 Click 이벤트를 프로그래밍 방식으로 실행하여 실제 “다운로드”를 발생시키는 데 문제가있었습니다.

내가 한 것은 “보이지 않는”IFRAME을 사용하는 것이 었으며 5 개의 브라우저 모두에서 작동했습니다!

그래서 여기에 내가 생각해 낸 내용이 있습니다. [저는 결코 HTML / Javascript 전문가가 아니며 관련 코드 만 포함했습니다.]

HTML (관련 비트 조각)

<div id="docxOutput">
<iframe id="ifOffice" name="ifOffice" width="0" height="0"
    hidden="hidden" seamless='seamless' frameBorder="0" scrolling="no"></iframe></div>

자바 스크립트

//url to call in the controller to get MS-Excel xml
var _lnkToControllerExcel = '@Url.Action("ExportToExcel", "Home")';
$("#btExportToExcel").on("click", function (event) {
    event.preventDefault();

    $("#ProgressDialog").show();//like an ajax loader gif

    //grab the basket as xml
    var keys = GetMyKeys();//returns delimited list of keys (for selected items from UI)

    //potential problem - the querystring might be too long??
    //2K in IE8
    //4096 characters in ASP.Net
    //parameter key names must match signature of Controller method
    var qsParams = [
    'keys=' + keys,
    'locale=' + '@locale'
    ].join('&');

    //The element with id="ifOffice"
    var officeFrame = $("#ifOffice")[0];

    //construct the url for the iframe
    var srcUrl = _lnkToControllerExcel + '?' + qsParams;

    try {
        if (officeFrame != null) {
            //Controller method can take up to 4 seconds to return
            officeFrame.setAttribute("src", srcUrl);
        }
        else {
            alert('ExportToExcel - failed to get reference to the office iframe!');
        }
    } catch (ex) {
        var errMsg = "ExportToExcel Button Click Handler Error: ";
        HandleException(ex, errMsg);
    }
    finally {
        //Need a small 3 second ( delay for the generated MS-Excel XML to come down from server)
        setTimeout(function () {
            //after the timeout then hide the loader graphic
            $("#ProgressDialog").hide();
        }, 3000);

        //clean up
        officeFrame = null;
        srcUrl = null;
        qsParams = null;
        keys = null;
    }
});

C # SERVER-SIDE (코드 조각) @Drew는 XmlActionResult라는 사용자 지정 ActionResult를 만들었습니다.

컨트롤러의 액션에서 XML을 ActionResult로 반환 하시겠습니까?

내 컨트롤러 방법 (ActionResult 반환)

  • XML을 생성하는 SQL Server 저장 프로 시저에 keys 매개 변수를 전달합니다.
  • XML은 xslt를 통해 MS-Excel xml (XmlDocument)로 변환됩니다.
  • 수정 된 XmlActionResult의 인스턴스를 만들어 반환

    XmlActionResult 결과 = 새로운 XmlActionResult (excelXML, “application / vnd.ms-excel”); 문자열 버전 = DateTime.Now.ToString ( “dd_MMM_yyyy_hhmmsstt”); 문자열 fileMask = “LabelExport_ {0} .xml”;
    result.DownloadFilename = string.Format (fileMask, 버전); 결과 반환;

@Drew가 생성 한 XmlActionResult 클래스의 주요 수정 사항입니다.

public override void ExecuteResult(ControllerContext context)
{
    string lastModDate = DateTime.Now.ToString("R");

    //Content-Disposition: attachment; filename="<file name.xml>"
    // must set the Content-Disposition so that the web browser will pop the open/save dialog
    string disposition = "attachment; " +
                        "filename=\"" + this.DownloadFilename + "\"; ";

    context.HttpContext.Response.Clear();
    context.HttpContext.Response.ClearContent();
    context.HttpContext.Response.ClearHeaders();
    context.HttpContext.Response.Cookies.Clear();
    context.HttpContext.Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);// Stop Caching in IE
    context.HttpContext.Response.Cache.SetNoStore();// Stop Caching in Firefox
    context.HttpContext.Response.Cache.SetMaxAge(TimeSpan.Zero);
    context.HttpContext.Response.CacheControl = "private";
    context.HttpContext.Response.Cache.SetLastModified(DateTime.Now.ToUniversalTime());
    context.HttpContext.Response.ContentType = this.MimeType;
    context.HttpContext.Response.Charset = System.Text.UTF8Encoding.UTF8.WebName;

    //context.HttpContext.Response.Headers.Add("name", "value");
    context.HttpContext.Response.Headers.Add("Last-Modified", lastModDate);
    context.HttpContext.Response.Headers.Add("Pragma", "no-cache"); // HTTP 1.0.
    context.HttpContext.Response.Headers.Add("Expires", "0"); // Proxies.

    context.HttpContext.Response.AppendHeader("Content-Disposition", disposition);

    using (var writer = new XmlTextWriter(context.HttpContext.Response.OutputStream, this.Encoding)
    { Formatting = this.Formatting })
        this.Document.WriteTo(writer);
}

기본적으로 그렇습니다. 그것이 다른 사람들을 돕기를 바랍니다.