এক্সিমারসাল্ট হিসাবে কোনও নিয়ন্ত্রণকারীর ক্রিয়া থেকে এক্সএমএল ফেরত দেবেন?


139

এএসপি.এনইটি এমভিসিতে একটি নিয়ামকের ক্রিয়া থেকে এক্সএমএল ফেরার সর্বোত্তম উপায় কী? জেএসওএন ফিরে আসার একটি দুর্দান্ত উপায় আছে তবে এক্সএমএল এর জন্য নয়। আমাকে কি ভিউয়ের মাধ্যমে এক্সএমএলকে সত্যিই রুট করতে হবে, অথবা আমার রেসপন্সের সেরা-অনুশীলন পদ্ধতিটি করা উচিত না itএটি লিখুন?

উত্তর:


114

এমভিসিসিবিট -এর এক্সএমএল রেজাল্ট অ্যাকশন ব্যবহার করুন ।

রেফারেন্সের জন্য এখানে তাদের কোড:

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);
        }
    }
}

12
এখানে ক্লাসটি সরাসরি এমভিসি কন্ট্রিবিব প্রকল্প থেকে নেওয়া হয়। আপনার নিজের ঘূর্ণায়মান হিসাবে যোগ্যতা অর্জন করে কিনা তা নিশ্চিত নন।
সেলিং জুডো

3
আপনি যদি এইএসপি.নেট এমভিসি কনভেনশন অনুসরণ করছেন তবে আপনি এই ক্লাসটি কোথায় রাখবেন? কন্ট্রোলার ফোল্ডার? আপনি নিজের ভিউমোডেলগুলি একই জায়গায় রেখেছেন, সম্ভবত?
পি.কম্পবেল ২২ শে

7
রাউটিং, ইত্যাদি ফলাফল ফিল্টার: @pcampbel, আমি আমার প্রকল্পের মূল পৃথক ফোল্ডার ক্লাস প্রতি ধরনের জন্য তৈরি পছন্দ
এন্থনি Serdyukov

ব্যবহার XmlSerialiserএবং সদস্য টীকা বজায় রাখা কঠিন হতে পারে। যেহেতু লুক এই উত্তর পোস্ট করেছে (প্রায় চার বছর আগে), তাই লিনাক থেকে এক্সএমএল বেশিরভাগ সাধারণ পরিস্থিতিতে নিজেকে আরও মার্জিত এবং শক্তিশালী প্রতিস্থাপন হিসাবে প্রমাণ করেছে। এটি কীভাবে করা যায় তার উদাহরণের জন্য আমার উত্তর দেখুন out
ড্র নোকস

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

1
বাহ, এটি আমাকে সত্যই সহায়তা করেছিল, তবে তখন আমি কেবল এমভিসি জিনিস দিয়েই শুরু করতে শুরু করি।
ডেনিস ভালিভ

আপনি যদি লিনক থেকে এক্সএমএল এর সাথে কাজ করছেন, দস্তাবেজের একটি স্ট্রিং ফর্ম তৈরি করা ব্যয়বহুল - স্ট্রিমগুলির সাথে কাজ করা ভাল
ড্র নোকস

2
@ ড্রু নোকস: না, তা নয়। আপনি যদি সরাসরি HTTPContext.Response.Output স্ট্রিমে লিখেন তবে আপনি WinXP ভিত্তিক সার্ভারগুলিতে একটি YSOD পাবেন। এটি ভিস্তা + এ স্থির করা হয়েছে বলে মনে হয়, বিশেষত সমস্যাযুক্ত যদি আপনি উইন্ডোজ 7 এ বিকাশ করেন এবং উইন্ডোজ এক্সপি (সার্ভার 2003?) এ স্থাপন করেন। যদি আপনি তা করেন তবে আপনাকে প্রথমে একটি মেমরি স্ট্রিম লিখতে হবে এবং তারপরে মেমরি স্ট্রিমটিকে আউটপুট স্ট্রিমে অনুলিপি করতে হবে ...
স্টিফান স্টিগার

6
@ গুপ্তচর, ঠিক আছে আমি এই বিষয়টি পুনরায় ফিরিয়ে আনব: আপনি যখন 11 বছরের পুরানো কম্পিউটিং সিস্টেমে কোনও ত্রুটি প্রদর্শন করে কাজ না করেন তবে স্ট্রিমগুলি ব্যবহার করে বরাদ্দ / সংগ্রহ / মেমরি-বহিরাগততাগুলি এড়াতে পারলে স্ট্রিংগুলি তৈরি করা ব্যর্থ ।
ড্র নোকস

1
পরিবর্তে আপনি application/xmlমাইমটাইপটি ব্যবহার করতে চাইতে পারেন ।
ফ্রেড

32

যদি আপনি দুর্দান্ত লিনাক-টু-এক্সএমএল কাঠামো ব্যবহার করে এক্সএমএল তৈরি করে থাকেন তবে এই পদ্ধতিটি সহায়ক হবে।

আমি 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আপনার জন্য এক্সএমএলকে সিরিয়ালিয়াল করে।

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);
    }
}

আপনি একটি মাইম টাইম (যেমন application/rss+xml) এবং আপনার প্রয়োজনে আউটপুট ইন্ডেন্ট করা উচিত কিনা তা নির্দিষ্ট করতে পারেন। উভয় বৈশিষ্ট্যের বুদ্ধিমান ডিফল্ট রয়েছে।

আপনার যদি ইউটিএফ 8 ব্যতীত অন্য কোনও এনকোডিং দরকার হয় তবে তার জন্যও কোনও সম্পত্তি যুক্ত করা সহজ।


আপনি কি মনে করেন কোনও এপিআই নিয়ামক ব্যবহারের জন্য এটি সংশোধন করা সম্ভব?
রে অ্যাকলে

@ রায়একলে, আমি জানি না যে আমি এখনও নতুন ওয়েব এপিআইয়ের জিনিস চেষ্টা করে দেখিনি। যদি আপনি এটি সন্ধান করেন তবে আমাদের জানান।
ড্রয় নোকস

আমার ধারণা আমি API কন্ট্রোলার প্রশ্ন (আমি সাধারণত এমভিসি স্টাফ করি না) দিয়ে ভুল ট্র্যাকে ছিলাম। আমি কেবল এটি নিয়মিত নিয়ামক হিসাবে প্রয়োগ করেছি এবং এটি দুর্দান্ত কাজ করেছে।
রায় অ্যাকলে

দুর্দান্ত কাজ ড্র। আমি আমার প্রয়োজনের জন্য আপনার এক্সএমএলঅ্যাকশনআরসাল্টের গন্ধ ব্যবহার করছি। আমার দেব পরিবেশ: এএসপি.এনইটি 4 এমভিসি আমি আমার কন্ট্রোলারের পদ্ধতিটি কল করি (এক্সএমএলএকশনআরসোল্ট ফিরিয়ে দেয় - এমএস-এক্সেলের জন্য একটি রূপান্তরিত এক্সএমএল সম্বলিত) অজ্যাক্স থেকে। আজাক্স সাফল্য ফাংশনে একটি ডেটা প্যারামিটার রয়েছে যাতে রূপান্তরিত এক্সএমএল থাকে। ব্রাউজার উইন্ডোটি চালু করতে এবং সেভএ ডায়ালগ প্রদর্শন করতে বা কেবল এক্সেল খুলতে কীভাবে এই ডেটা প্যারামিটারটি ব্যবহার করবেন?
উত্তম

@ শীর, আপনি যদি ব্রাউজারটি ফাইলটি চালু করতে চান তবে আপনাকে এজেএক্সের মাধ্যমে এটি লোড করা উচিত নয়। আপনার ক্রিয়া পদ্ধতিতে সরাসরি নেভিগেট করুন। MIME প্রকারটি ব্রাউজার দ্বারা কীভাবে পরিচালনা করা হবে তা নির্ধারণ করবে। application/octet-streamএটি ডাউনলোড করতে বাধ্য করার মতো কিছু ব্যবহার করে । আমি জানি না মাইম টাইপটি কী এক্সেল চালু করে, তবে আপনার এটি অনলাইনে সহজেই খুঁজে পেতে সক্ষম হওয়া উচিত।
ড্রয় নোকস

26

আপনি যদি কেবলমাত্র একটি অনুরোধের মাধ্যমে এক্সএমএল ফেরত পেতে আগ্রহী হন এবং আপনার এক্সএমএল "অংশ" থাকে, আপনি কেবল (আপনার নিয়ামকের ক্রিয়া হিসাবে) করতে পারেন:

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


4

সিতিকোর প্রকল্পের জন্য আমাকে সম্প্রতি এটি করতে হয়েছিল যা সীতাকোর আইটেম এবং তার বাচ্চাদের থেকে এক্সএমএল ডকুমেন্ট তৈরির জন্য একটি পদ্ধতি ব্যবহার করে এবং এটিকে ফাইল হিসাবে নিয়ামক অ্যাকশন রেজাল্ট থেকে ফিরিয়ে দেয়। আমার সমাধান:

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

2

অবশেষে এই কাজটি পরিচালনা করার জন্য পরিচালনা করুন এবং ভেবেছিলাম যে এখানে অন্যদের ব্যথা বাঁচানোর আশায় কীভাবে নথিবদ্ধ করব।

পরিবেশ

  • VS2012
  • এসকিউএল সার্ভার 2008 আর 2
  • .NET 4.5
  • এএসপি.নেট এমভিসি 4 (রেজার)
  • উইন্ডোজ 7

সমর্থিত ওয়েব ব্রাউজারগুলি

  • ফায়ারফক্স 23
  • আইই 10
  • ক্রোম 29
  • অপেরা 16
  • সাফারি 5.1.7 (উইন্ডোজের জন্য সর্বশেষ?)

আমার কাজটি একটি ইউআই বোতাম ক্লিকে ছিল, আমার কন্ট্রোলারে একটি পদ্ধতি কল করুন (কিছু প্যারাম দিয়ে) এবং তারপরে এটি একটি এক্সএসল্ট রূপান্তর মাধ্যমে একটি এমএস-এক্সেল এক্সএমএল ফিরিয়ে আনবে। ফিরে আসা এমএস-এক্সেল এক্সএমএল এর পরে ব্রাউজারটিকে ওপেন / সেভ ডায়ালগটি পপআপ করতে দেয়। এটিতে সমস্ত ব্রাউজারে কাজ করতে হয়েছিল (উপরে তালিকাভুক্ত)।

প্রথমে আমি আজাক্সের সাথে ফাইল ফাইলের জন্য "ডাউনলোড" অ্যাট্রিবিউট দিয়ে একটি গতিশীল অ্যাঙ্কর তৈরি করার চেষ্টা করেছি, তবে এটি কেবল 5 বা 3 ব্রাউজারের (এফএফ, ক্রোম, অপেরা) জন্য কাজ করেছে, আইই বা সাফারি নয়। এবং প্রকৃত "ডাউনলোড" হওয়ার কারণ হিসাবে অ্যাঙ্কারের ক্লিক ইভেন্টটিকে প্রোগ্রামগতভাবে ফায়ার করার চেষ্টা করার সমস্যা রয়েছে।

আমি যা করে শেষ করেছি তা হল একটি "অদৃশ্য" আইএফআরএম ব্যবহার করে এবং এটি 5 টি ব্রাউজারের জন্য কাজ করে!

সুতরাং আমি এখানে যা এলাম তা এখানে: [দয়া করে নোট করুন যে আমি কোনওভাবেই এইচটিএমএল / জাভাস্ক্রিপ্ট গুরু নই এবং কেবলমাত্র প্রাসঙ্গিক কোডই অন্তর্ভুক্ত করেছি]

এইচটিএমএল (প্রাসঙ্গিক বিটের স্নিপেট)

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

অবশ্যই JAVASCRIPT

//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;
    }
});

সি # সার্ভার-সাইড (কোড স্নিপেট) @ ড্র একটি XMLActionResult নামে একটি কাস্টম অ্যাকশনারসাল্ট তৈরি করেছে যা আমি আমার উদ্দেশ্যে পরিবর্তিত করেছি।

এক্সিমারসাল্ট হিসাবে কোনও নিয়ন্ত্রণকারীর ক্রিয়া থেকে এক্সএমএল ফেরত দেবেন?

আমার নিয়ামক পদ্ধতি (অ্যাকশন রেজাল্ট প্রদান করে)

  • কীগুলির প্যারামিটারগুলি একটি এসকিউএল সার্ভারের সঞ্চিত প্রোকগুলিতে পাস করে যা একটি এক্সএমএল উত্পন্ন করে
  • এক্সএমএল এর পরে এক্সএসল্টের মাধ্যমে একটি এমএস-এক্সেল এক্সএমএল (এক্সএমএল ডকুমেন্ট) রূপান্তরিত হয়
  • পরিবর্তিত XMLActionResult এর উদাহরণ তৈরি করে এটি প্রদান করে

    এক্সএমএলএকশনআরসাল্ট রেজাল্ট = নতুন এক্সএমএলএকশনআরসাল্ট (এক্সেলএক্সএমএল, "অ্যাপ্লিকেশন / ভিএনডি.এমএস-এক্সেল"); স্ট্রিং সংস্করণ = ডেটটাইম.নো। টুস্ট্রিং ("ডিডি_এমএমএম_ইউই_হম্মসস্টেট"); স্ট্রিং ফাইলমাস্ক = "LabelExport_ {0} .xML";
    ফলাফল.ডাউনলোডফিলনাম = স্ট্রিং.ফর্ম্যাট (ফাইলমাস্ক, সংস্করণ); প্রত্যাবর্তনের ফলাফল;

@ ড্র তৈরি করা 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);
}

মূলত এটি ছিল। আশা করি এটি অন্যকে সহায়তা করবে।


1

একটি সাধারণ বিকল্প যা আপনাকে স্ট্রীম এবং যা কিছু ব্যবহার করতে দেয় return File(stream, "text/xml");


0

এটি করার একটি সহজ উপায় এখানে:

        var xml = new XDocument(
            new XElement("root",
            new XAttribute("version", "2.0"),
            new XElement("child", "Hello World!")));
        MemoryStream ms = new MemoryStream();
        xml.Save(ms);
        return File(new MemoryStream(ms.ToArray()), "text/xml", "HelloWorld.xml");

কেন এটি দুটি মেমরি স্ট্রিম তৈরি করে? কেন এটি msসরাসরি নতুনকে অনুলিপি না করে সরাসরি পাস করবেন না ? উভয় বস্তুর একই জীবনকাল হবে।
jpaugh

একটি করুন ms.Position=0এবং আপনি মূল স্মৃতিপ্রবাহটি ফিরে আসতে পারেন। তারপরে আপনি পারেনreturn new FileStreamResult(ms,"text/xml");
কার্টার মেডলিন

0

এক্সডোকামেন্টের সেভ () পদ্ধতিটি ব্যবহার করে এমন ড্রউ নোকস থেকে উত্তরের একটি ছোট প্রকরণ ।

public sealed class XmlActionResult : ActionResult
{
    private readonly XDocument _document;
    public string MimeType { get; set; }

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

        _document = document;

        // Default values
        MimeType = "text/xml";
    }

    public override void ExecuteResult(ControllerContext context)
    {
        context.HttpContext.Response.Clear();
        context.HttpContext.Response.ContentType = MimeType;
        _document.Save(context.HttpContext.Response.OutputStream)
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.