Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get a response "stream" from an action in MVC3/Razor?

I am using MVC3, .NET4, C#.

I need to create some XHTML using a Razor View. I do this via an Action.

    public ActionResult RenderDoc(int ReportId)
    {
        //A new document is created.

        return View();
    }

I then need to take the output from this and convert it to a Word Doc. I am using a 3rd party component to do this and it expects a "stream" or a "file" for the XHTML source that is read in for conversion to a DOC, like the following:

document.Open(MyXhtmlStream,FormatType.Html,XHTMLValidationType.Transitional);

My Question:

What would be a good way to call the "RenderDoc" Action and obtain the result as a stream to feed into "MyXhtmlStream".

Many thanks.

EDIT: I have had another idea !!!

1) Render the View within the action to create a String(XHTMLString). I have seen a method to do this on SO.

2) Create a MemoryStream and put this string into it.

Stream MyStream = New MemoryStream("XHTMLString and encoding method");

EDIT2: Based on Darin's answer

I need to clasyify a little further, and I hope to do this via tweaking Darin's code for my purpose.

 public class XmlDocumentResult : ActionResult
 {
  private readonly string strXhtmlDocument;
  public XmlDocumentResult(string strXhtmlDocument)
  {
    this.strXhtmlDocument = strXhtmlDocument;
  }

  public override void ExecuteResult(ControllerContext context)
  {
    WordDocument myWordDocument = new WordDocument();
    var response = context.HttpContext.Response;
    response.ContentType = "text/xml";
    myWordDocument.Open(response.OutputStream, FormatType.Html, XHTMLValidationType.Transitional);
  }
 }

The above is closer to what I need. Note the 3rd Party WordDocument type. So there is still the issue of how I get the "strXhtmlDocument" into the "Response.OutputStream?

like image 435
SamJolly Avatar asked Apr 19 '13 12:04

SamJolly


1 Answers

I would just write a custom ActionResult to handle that:

public class XmlDocumentResult : ActionResult
{
    private readonly Document document;
    public XmlDocumentResult(Document document)
    {
        this.document = document;
    }

    public override void ExecuteResult(ControllerContext context)
    {
        var response = context.HttpContext.Response;
        response.ContentType = "text/xml";
        document.Open(response.OutputStream, FormatType.Html, XHTMLValidationType.Transitional);
    }
}

You could of course adjust the response Content-Type if necessary and also append a Content-Disposition header if you want.

And then simply have my controller action return this custom action result:

public ActionResult RenderDoc(int reportId)
{
    Document document = repository.GetDocument(reportId);
    return new XmlDocumentResult(document);
}

Now the controller action doesn't need to handle plumbing code anymore. The controller action does what a typical controller action is supposed to do:

  1. Query the Model
  2. Pass this model to an ActionResult

In your case the model is this Document class or whatever it is called.

like image 123
Darin Dimitrov Avatar answered Sep 28 '22 12:09

Darin Dimitrov