Как прикрепить XML к.net Mail Attachment с помощью MemoryStream?
У меня есть представление cshtml в MVC, заполненный XML, такие как:
@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 для некоторых ограничений, которые я получил на сервере, так что это не вариант для меня. Я только хочу создать файл.xls с помощью Xml и отправить его, используя почту.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);
}
так как я могу достичь этого?
2 ответа
Я не смог реализовать просмотр бритвы успешно, но после 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;
}
Затем я сохранил его MemoryStream
с UTF8
Кодирование..
// Create attachment
// Add XML to MemoryStream /* MyXmlString */
MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(XmlToImplement(id)));
Затем определили ContentType
как Excel
// Content Type
ContentType contentType = new ContentType("application/vnd.ms-excel");
contentType.Name = UserName + "(" + FileDate + ").xls";
Наконец я прикрепил его к почте.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 в почтовое вложение, и я надеюсь, что это поможет другим, решающим эту проблему.
В зависимости от того, какая версия Excel или какие функции вам нужны. Excel писатель Карлос Ag может быть достаточно. это немного устарело, но работает для простых книг Excel.
Если вам нужно свернуть шаблон самостоятельно, посмотрите Шаблоны Razor Generator, чтобы представить модель в виде строки. передать строку 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();
}
}
}
следуя инструкциям на домашней странице проекта, установите custom tool
(просмотреть окна свойств) RazorGenerator
,
тогда вы можете сделать что-то это
string excelXml = new NameOfMyView { Model = theData }.TransformText();
//write string to memmory stream, attach to MailMessage