2012-12-05 66 views
2

我有一個MVC視圖CSHTML充滿XML如:如何使用MemoryStream將Xml附加到.net郵件附件?

@model myproject.net.Models.mymodel 
@{ 
    Layout = null; 
    Response.ContentType = "application/vnd.ms-excel"; 
    Response.AddHeader("Content-Disposition", "attachment; " + "filename=" + 
     Model.myusername.ToString() + "(" + 
     Model.mydate.Date.ToShortDateString() + ").xls"); 
} 

<?xml version="1.0" encoding="utf-8"?> 
<ss:Workbook xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"> 
    <Styles> 
     <Style ss:ID="s25"> 
      <Alignment ss:Horizontal="Center" ss:Vertical="Bottom"/> 
      <Borders> 
       <Border ss:Position="Bottom" ss:LineStyle="Continuous" ss:Weight="1"/> 
      </Borders> 
      <Interior ss:Color="#FFA500" ss:Pattern="Solid"/> 
     </Style> 
    </Styles> 
    <ss:Worksheet ss:Name="Sheet1"> 
     <ss:Table> 
     @if (Model.someNumerableContent.Count > 0) 
     { 
      <!-- MyContent --> 
      <ss:Row> 
       <ss:Cell><ss:Data ss:Type="String">Content Header</ss:Data></ss:Cell> 
      </ss:Row> 
      <ss:Row> 
       <ss:Cell><ss:Data ss:Type="String">SubHeader 1</ss:Data></ss:Cell> 
       <ss:Cell><ss:Data ss:Type="String">SubHeader 2</ss:Data></ss:Cell> 
       <ss:Cell><ss:Data ss:Type="String">SubHeader 3</ss:Data></ss:Cell> 
       <ss:Cell><ss:Data ss:Type="String">SubHeader 4</ss:Data></ss:Cell> 
       <ss:Cell><ss:Data ss:Type="String">SubHeader 5</ss:Data></ss:Cell> 
      </ss:Row> 
      foreach (var subContent in Model.someNumerableContent) 
      { 
      <ss:Row> 
       <ss:Cell><ss:Data ss:Type="String">@subContent.mydate.Date.ToShortDateString()</ss:Data></ss:Cell> 
       <ss:Cell><ss:Data ss:Type="String">@subContent.number</ss:Data></ss:Cell> 
       <ss:Cell><ss:Data ss:Type="String">@subContent.name</ss:Data></ss:Cell> 
       <ss:Cell><ss:Data ss:Type="String">@subContent.surname</ss:Data></ss:Cell> 
       <ss:Cell><ss:Data ss:Type="String">@subContent.issue</ss:Data></ss:Cell> 
      </ss:Row> 
      } 
      <ss:Row> </ss:Row> 
     } 
     </ss:Table> 
    </ss:Worksheet> 
</ss:Workbook> 

,我想將其轉換爲.xls文件和附加到郵件,而不會有任何保存它。 但無法弄清楚我如何實現這一點。我不能使用office.interop的一些限制,我得到了服務器,所以它不是我的選擇。我只想通過Xml創建一個.xls文件並使用.net郵件發送它。到目前爲止,我已經這樣做了:

// Memory stream for the xml file 
using (MemoryStream memoryStream = new MemoryStream()) 
{ 
    //             Can i use something like this? 
    byte[] contentAsBytes = Encoding.Default.GetBytes(View("ExportToExcel").ToString()); 
    memoryStream.Write(contentAsBytes, 0, contentAsBytes.Length); 
    // Set the position to the beginning of the stream. 
    memoryStream.Seek(0, SeekOrigin.Begin); 
    // Create attachment 
    ContentType contentType = new ContentType(); 
    contentType.MediaType = MediaTypeNames.Text.Xml; 
    contentType.Name = UserName + "(" + FileDate + ").xls"; 
    // Attach 
    mail.Attachment = new Attachment(memoryStream, contentType); 
} 

那麼我該如何實現這個?

+1

我們做了類似的事情,總是將它保存到本地臨時文件中,但不確定它可以在內存中完成。 –

+0

@BradPatton多數民衆贊成在實際的事情..我的意思是認爲你可以附加內存,這將使它更安全和硬盤免費。 –

+0

確切的問題是什麼?將模型渲染爲xml或將文件(內存流)附加到電子郵件中? –

回答

2

我不可能實現的Razor視圖全成,但它的工作30小時後。我發現另一種方法..

首先我創建如下面的了XmlString:

public String XmlToImplement(int id) 
{ 
    // Add values from db to model 
    MyModel model = new MyModel(); 
    model.contents = db.contents.Where(c => c.MyData.id == id).ToList(); 
    // XmlString 
    String XmlString = @"<?xml version='1.0' encoding='utf-8'?> 
    <ss:Workbook xmlns='urn:schemas-microsoft-com:office:spreadsheet' 
       xmlns:o='urn:schemas-microsoft-com:office:office' 
       xmlns:x='urn:schemas-microsoft-com:office:excel' 
       xmlns:ss='urn:schemas-microsoft-com:office:spreadsheet' 
       xmlns:html='http://www.w3.org/TR/REC-html40'> 
     <Styles> 
      <Style ss:ID='s25'> 
       <Alignment ss:Horizontal='Center' ss:Vertical='Bottom'/> 
       <Borders> 
        <Border ss:Position='Bottom' ss:LineStyle='Continuous' ss:Weight='1'/> 
       </Borders> 
       <Interior ss:Color='#FFA500' ss:Pattern='Solid'/> 
      </Style> 
     </Styles> 
     <ss:Worksheet ss:Name='Sheet1'> 
      <ss:Table>"; 
      if (model.contents.Count > 0) 
      { 
       XmlString = XmlString + @"<!-- MyModelData --> 
       <ss:Row> 
        <ss:Cell><ss:Data ss:Type='String'> MyModelData </ss:Data></ss:Cell> 
       </ss:Row> 
       <ss:Row> 
        <ss:Cell><ss:Data ss:Type='String'>Date</ss:Data></ss:Cell> 
        <ss:Cell><ss:Data ss:Type='String'>Number</ss:Data></ss:Cell> 
        <ss:Cell><ss:Data ss:Type='String'>Name/Surname</ss:Data></ss:Cell> 
       </ss:Row>"; 
       foreach (var content in model.contents) 
       { 
        XmlString = XmlString + @"<ss:Row>"; 
        XmlString = XmlString + @"<ss:Cell><ss:Data ss:Type='String'>" + content.thedate.Date.ToShortDateString() + "</ss:Data></ss:Cell>"; 
        XmlString = XmlString + @"<ss:Cell><ss:Data ss:Type='String'>" + content.number + "</ss:Data></ss:Cell>"; 
        XmlString = XmlString + @"<ss:Cell><ss:Data ss:Type='String'>" + content.namesurname+ "</ss:Data></ss:Cell>"; 
        XmlString = XmlString + @"</ss:Row>"; 
       } 
       // An empty row for next value set 
       XmlString = XmlString + "<ss:Row> </ss:Row>"; 
      } 
      XmlString = XmlString + @"</ss:Table> 
     </ss:Worksheet> 
    </ss:Workbook>"; 
    return XmlString; 
} 

然後我將其與編碼UTF8保存到MemoryStream ..

// Create attachment 
// Add XML to MemoryStream           /* MyXmlString */ 
MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(XmlToImplement(id))); 

然後定義ContentTypeExcel

// Content Type 
ContentType contentType = new ContentType("application/vnd.ms-excel"); 
contentType.Name = UserName + "(" + FileDate + ").xls"; 

At最後我附加到.net郵件

// Attach 
mail.Attachment = new Attachment(memoryStream, contentType); 
mail.Attachment.NameEncoding = UTF8Encoding.UTF8; 
mail.Attachment.TransferEncoding = TransferEncoding.Base64; 
mail.Attachment.ContentDisposition.DispositionType = DispositionTypeNames.Attachment; 

它工作得很好。我可能無法將XML視圖轉換爲郵件附件,但我可以輕鬆將一個xml字符串轉換爲郵件附件,我希望這有助於其他人解決這個問題。

1

取決於什麼版本的Excel或您需要什麼功能。 Carlos Ag's Excel Writer就足夠了。這有點過時,但適用於簡單的Excel工作簿。

如果您需要自行滾動模板,請檢查Razor Generator Templates以將模型呈現爲字符串。將字符串傳遞給Stream並附加到電子郵件。

更新

使用剃刀模板首先你需要一個視圖

@* Generator: Template *@ 
@inherits The.NameSpace.RazorTemplateBase<dynamic> 

@functions { 
    public object Model { get; set; } 
} 

<your typical markup goes here...> 

,那麼你需要的基類

public abstract class RazorTemplateBase<dynamic> 
{ 
    public static string RootAddress { get; set; } 

    public virtual RazorTemplateBase<dynamic> Layout { get; set; } 

    private readonly StringBuilder generatingEnvironment = new StringBuilder(); 

    public abstract void Execute(); 

    public void WriteLiteral(string textToAppend) 
    { 
     if (string.IsNullOrEmpty(textToAppend)) 
     { 
      return; 
     } 
     generatingEnvironment.Append(textToAppend); 
    } 

    public void Write(object value) 
    { 
     if ((value == null)) 
     { 
      return; 
     } 
     string stringValue; 
     var t = value.GetType(); 
     var method = t.GetMethod("ToString", new [] { typeof(IFormatProvider) }); 
     if ((method == null)) 
     { 
      stringValue = value.ToString(); 
     } 
     else 
     { 
      stringValue = ((string)(method.Invoke(value, new object[] { CultureInfo.InvariantCulture }))); 
     } 
     WriteLiteral(stringValue); 
    } 

    string content; 

    public string RenderBody() 
    { 
     return content; 
    } 

    public string TransformText() 
    { 
     Execute(); 
     if (Layout != null) 
     { 
      Layout.content = generatingEnvironment.ToString(); 
      return Layout.TransformText(); 
     } 
     else 
     { 
      return generatingEnvironment.ToString(); 
     } 
    } 
} 

下設置的項目homepage的說明custom tool(查看正確的視窗)RazorGenerator

那麼你可以做一些這

string excelXml = new NameOfMyView { Model = theData }.TransformText(); 
//write string to memmory stream, attach to MailMessage 
+0

我該如何實現我的XML到它?我的意思是我怎樣才能將它作爲viewresult ||返回串和靠近流?你能解釋一下嗎?一些編碼的例子可能?我在「Razor Generator Templates」鏈接中嘗試了一些例子,但是我沒有成功。 –

+0

到目前爲止它的有用的感謝,但我嚴重無法讓myView實現'string excelXml = new myView {Model = mymodel.complaints} .TransformText();'當然它不是它的使用方式。 –

+0

1.你有剃鬚刀的風景嗎? 2.該視圖是否繼承'RazorTemplateBase '? 3.視圖是否包含'@ * Generator:Template * @'聲明作爲第一行? 4.視圖是否使用'RazorGenerator'作爲自定義工具?如果是這樣,它應該自動創建一個類(類似於webforms代碼),然後可以將該視圖實例化爲一個類並調用'TransformText()'。 –