2009-06-03 14 views
24

से आउटपुट स्ट्रीम को लिखना कुछ अजीब कारणों से, मैं सीधे नियंत्रक कार्रवाई से प्रतिक्रिया स्ट्रीम पर HTML लिखना चाहता हूं। (मैं एमवीसी अलगाव को समझता हूं, लेकिन यह एक विशेष मामला है।)कार्रवाई

क्या मैं सीधे HttpResponse स्ट्रीम में लिख सकता हूं? उस स्थिति में, IView ऑब्जेक्ट को नियंत्रक कार्रवाई वापस करनी चाहिए? क्या मैं 'शून्य' वापस कर सकता हूं?

उत्तर

8

हाँ, आप सीधे प्रतिक्रिया को लिख सकते हैं

Controller पर Content तरीकों पर एक नजर डालें। पूरा करने के बाद, आप CompleteRequest() को कॉल कर सकते हैं और आपको कुछ भी वापस करने की आवश्यकता नहीं है।

उदाहरण के लिए:

// GET: /Test/Edit/5 
public ActionResult Edit(int id) 
{ 

    Response.Write("hi"); 
    HttpContext.ApplicationInstance.CompleteRequest(); 

    return View();  // does not execute! 
} 
+1

आपको Response.End() http://stevesmithblog.com/blog/use-httpapplication-completerequest-instead-of-response-end/ –

+1

से बचने के लिए अपडेट किया जाना चाहिए CompleteRequest() का उपयोग करने के लिए। – womp

+1

अनुपलब्ध दृश्य के बारे में त्रुटियों से बचने के लिए "वापसी सामग्री (" ")" द्वारा "वापसी दृश्य()" को प्रतिस्थापित करने के लिए उपयोगी हो सकता है। लेकिन क्या यह दृष्टिकोण सुरक्षित रूप से है? –

5

अपनी खुद की कार्रवाई के परिणाम लिखें। यहाँ मेरा एक का एक उदाहरण है:

public class RssResult : ActionResult 
{ 
    public RssFeed RssFeed { get; set; } 

    public RssResult(RssFeed feed) { 
     RssFeed = feed; 
    } 

    public override void ExecuteResult(ControllerContext context) { 
     context.HttpContext.Response.ContentType = "application/rss+xml"; 
     SyndicationResourceSaveSettings settings = new SyndicationResourceSaveSettings(); 
     settings.CharacterEncoding = new UTF8Encoding(false); 
     RssFeed.Save(context.HttpContext.Response.OutputStream, settings); 
    } 
} 
43

मैं इस का उपयोग कर सामान्य MVC पैटर्न प्राप्त करने के लिए एक वर्ग FileResult से प्राप्त इस्तेमाल किया:

/// <summary> 
/// MVC action result that generates the file content using a delegate that writes the content directly to the output stream. 
/// </summary> 
public class FileGeneratingResult : FileResult 
{ 
    /// <summary> 
    /// The delegate that will generate the file content. 
    /// </summary> 
    private readonly Action<System.IO.Stream> content; 

    private readonly bool bufferOutput; 

    /// <summary> 
    /// Initializes a new instance of the <see cref="FileGeneratingResult" /> class. 
    /// </summary> 
    /// <param name="fileName">Name of the file.</param> 
    /// <param name="contentType">Type of the content.</param> 
    /// <param name="content">Delegate with Stream parameter. This is the stream to which content should be written.</param> 
    /// <param name="bufferOutput">use output buffering. Set to false for large files to prevent OutOfMemoryException.</param> 
    public FileGeneratingResult(string fileName, string contentType, Action<System.IO.Stream> content,bool bufferOutput=true) 
     : base(contentType) 
    { 
     if (content == null) 
      throw new ArgumentNullException("content"); 

     this.content = content; 
     this.bufferOutput = bufferOutput; 
     FileDownloadName = fileName; 
    } 

    /// <summary> 
    /// Writes the file to the response. 
    /// </summary> 
    /// <param name="response">The response object.</param> 
    protected override void WriteFile(System.Web.HttpResponseBase response) 
    { 
     response.Buffer = bufferOutput; 
     content(response.OutputStream); 
    } 
} 

नियंत्रक विधि अब इस तरह होगा:

public ActionResult Export(int id) 
{ 
    return new FileGeneratingResult(id + ".csv", "text/csv", 
     stream => this.GenerateExportFile(id, stream)); 
} 

public void GenerateExportFile(int id, Stream stream) 
{ 
    stream.Write(/**/); 
} 

ध्यान दें कि यदि बफरिंग बंद है,

stream.Write(/**/); 

बेहद धीमा हो जाता है। समाधान BufferedStream का उपयोग करना है। एक मामले में लगभग 100x तक बेहतर प्रदर्शन करना।

Unbuffered Output Very Slow

+0

इस प्रश्न का सबसे अच्छा जवाब। अच्छा विचार। – pylover

+0

अन्य उत्तरों हैंक – Andrey

+0

सर्वश्रेष्ठ उत्तर - बस एक बार फ़ाइल जोड़ें, और लचीली प्रतिनिधि पैरामीटर का उपयोग करके हर अवस्था में इस अवधारणा का पुन: उपयोग करें। – Froyke

3

देखें आप अपने खुद के परिणाम प्रकार प्राप्त करने के लिए नहीं करना चाहते हैं, तो आप बस Response.OutputStream को लिखने और new EmptyResult() लौट सकते हैं।

संबंधित मुद्दे