Archive for category MVC
WCF and Email Attachments
Posted by Kelly's Chronicles in .NET, C#, MVC, WCF on September 27, 2015
First off I want to apologize for being away so long. It has been a crazy ride to say the least.
So a colleague of mine ran into an issue with WCF and emailing attachments and asked for help. In this block of code below it would always fail at:
Attachment attachment = new Attachment(fileAttachment.ContentStream, fileAttachment.Name);” The error is : “Value cannot be null.
Parameter name: stream”
EmailSendInput emailSendInput = new EmailSendInput
{
Attachments = new List<Attachment>(),
Body = model.Body,
To = new List<string> { model.EmailTo },
From = model.EmailFrom,
Subject = model.EmailSubject
};
if (model.Files != null)
{
foreach (var currAttachment in model.Files)
{
if (currAttachment != null && currAttachment.ContentLength > 0)
{
// the filename needs to be nice looking
string fileName =
currAttachment.FileName.Substring(
currAttachment.FileName.LastIndexOf(@”\”, System.StringComparison.Ordinal) + 1,
currAttachment.FileName.Length
– currAttachment.FileName.LastIndexOf(@”\”, System.StringComparison.Ordinal) – 1);
var attachment = new Attachment(currAttachment.InputStream, fileName);
emailSendInput.Attachments.Add(attachment);
}
}
}
B2BMortgageDataServiceAgent b2BMortgageDataServiceAgent = new B2BMortgageDataServiceAgent();
EmailSendResponse emailSendResponse = b2BMortgageDataServiceAgent.SendEmail(emailSendInput);
if (!emailSendResponse.Success)
{
throw new Exception(emailSendResponse.Message);
}
}
public EmailSendResponse SendEmail(EmailSendInput input)
{
EmailSendResponse retVal = new EmailSendResponse();
try
{
string smtpServer = “”
string smtpPort = “”
using (var client = new SmtpClient(smtpServer, Convert.ToInt32(smtpPort)))
{
var mail = new MailMessage
{
From = new MailAddress(input.From),
Subject = input.Subject,
Body = input.Body
};
input.To.ForEach(t => mail.To.Add(t));
if (input.Attachments != null && input.Attachments.Count > 0)
{
foreach (var fileAttachment in input.Attachments)
{
//Code Crashes here
Attachment attachment = new Attachment(fileAttachment.ContentStream, fileAttachment.Name);
mail.Attachments.Add(attachment);
}
}
client.Send(mail);
}
retVal.Success = true;
}
catch (Exception exception)
{
retVal.Success = false;
LogUtil.LogException(exception);
retVal.Message = exception.ToString();
}
return retVal;
}
and then the contract:
[DataContract]
public class EmailSendInput
{
[DataMember]
public string From { get; set; }
[DataMember]
public List<string> To { get; set; }
[DataMember]
public string Subject { get; set; }
[DataMember]
public string Body { get; set; }
[DataMember]
public List<Attachment> Attachments { get; set; }
}
Implemented as:
public EmailSendResponse SendEmail(EmailSendInput input)
{
try
{
return this.dataAgent.SendEmail(input);
}
catch (Exception e)
{
this.logger.LogException(e, 2);
throw new FaultException(“An error occured in SendEmail. Error details : ” + this.BuildMessage(e));
}
}
and the Email response:
[DataContract]
public class EmailSendResponse
{
[DataMember]
public bool Success { get; set; }
[DataMember]
public string Message { get; set; }
}
So now we have the problem. I basically had to recreate his datamember for attachment in the contract EmailSendInput to a
public List<EmailEncodedAttachment> Attachments { get; set; }
and added a new contract called EmailEncodedAttachment and process how he was handling the attachment differently. I’ve also included the MVC controller calls in case it might help you as well.
SOLUTION:
[DataContract]
public class EmailSendInput
{
[DataMember]
public string From { get; set; }
[DataMember]
public List<string> To { get; set; }
[DataMember]
public string Subject { get; set; }
[DataMember]
public string Body { get; set; }
[DataMember]
public List<EmailEncodedAttachment> Attachments { get; set; }
}
[DataContract]
public class EmailEncodedAttachment
{
[DataMember]
public string Base64Attachment;
[DataMember]
public string Name;
/// <summary>
/// One of the System.Net.Mime.MediaTypeNames
/// </summary>
[DataMember]
public string MediaType;
}
}
retVal.Message = exception.ToString();
}
return retVal;
}
public EmailSendResponse SendEmail(EmailSendInput input)
{
EmailSendResponse retVal = new EmailSendResponse();
try
{
string smtpServer = ConfigurationManager.AppSettings[“SmtpServer”] ?? “url”;
string smtpPort = ConfigurationManager.AppSettings[“SmtpPort”] ?? “portnum”;
using (var client = new SmtpClient(smtpServer, Convert.ToInt32(smtpPort)))
{
var mail = new MailMessage
{
From = new MailAddress(input.From),
Subject = input.Subject,
Body = input.Body
};
input.To.ForEach(t => mail.To.Add(t));
if (input.Attachments != null && input.Attachments.Count > 0)
{
foreach (var fileAttachment in input.Attachments)
{
mail.Attachments.Add(this.CreateAttachment(fileAttachment));
}
}
client.Send(mail);
}
retVal.Success = true;
}
catch (Exception exception)
{
retVal.Success = false;
LogUtil.LogException(exception);
retVal.Message = exception.ToString();
}
return retVal;
}
The MVC controller action calls the service like so:
EmailSendInput emailSendInput = new EmailSendInput
{
Attachments = new List<EmailEncodedAttachment>(),
Body = model.Body,
To = new List<string> { model.EmailTo },
From = model.EmailFrom,
Subject = model.EmailSubject
};
if (model.Files != null)
{
foreach (var file in model.Files)
{
if (file != null && file.ContentLength > 0)
{
// the filename needs to be nice looking
string prettyFileName =
file.FileName.Substring(
file.FileName.LastIndexOf(@”\”, System.StringComparison.Ordinal) + 1,
file.FileName.Length
– file.FileName.LastIndexOf(@”\”, System.StringComparison.Ordinal) – 1);
var attachment = this.CreateAttachment(prettyFileName, file.InputStream);
emailSendInput.Attachments.Add(attachment);
}
}
}
B2BMortgageDataServiceAgent b2BMortgageDataServiceAgent = new B2BMortgageDataServiceAgent();
EmailSendResponse emailSendResponse = b2BMortgageDataServiceAgent.SendEmail(emailSendInput);
if (!emailSendResponse.Success)
{
throw new Exception(emailSendResponse.Message);
}
and finally the encoding method which makes this possible:
private EmailEncodedAttachment CreateAttachment(string fileName, Stream stream)
{
EmailEncodedAttachment att = new EmailEncodedAttachment
{
Name = fileName,
MediaType = System.Net.Mime.MediaTypeNames.Text.Plain
};
byte[] buffer = new byte[stream.Length];
stream.Read(buffer, 0, (int)stream.Length);
att.Base64Attachment = Convert.ToBase64String(buffer);
return att;
}
There you have it folks. I hope you have a great Sunday!
.NET, action, AppSettings, Attachment, Attachments, Body, BuildMessage, byte, c#, client, CODE, colleague, ConfigurationManager, ContentLength, ContentStream, controller, Convert, Count, Crashes, CreateAttachment, DataContract, DataMember, Email, EmailEncodedAttachment, EmailFrom, EmailSendInput, EmailSendResponse, EmailSubject, EmailTo, error, Exception, FaultException, filename, Files, foreach, From, InputStream, LastIndexOf, Length, List, LogException, LogUtil, MailMessage, MediaType, MediaTypeNames, Message, method, Mime, MVC, Name, Ordinal, parameter, Plain, prettyFileName, Read, response, retVal, Send, SendEmail, SmtpClient, SmtpPort, SmtpServer, solution, Stream, StringComparison, Subject, System, Text, Value, WCF
-
You are currently browsing the archives for the MVC category.
Archives
- April 2018
- January 2018
- December 2017
- June 2017
- May 2017
- May 2016
- April 2016
- September 2015
- July 2014
- June 2014
- November 2012
- October 2012
- June 2012
- May 2012
- April 2012
- January 2012
- September 2011
- August 2011
- July 2011
- May 2009
- April 2009
- March 2009
- February 2009
- January 2009
- December 2008
- November 2008
- October 2008
- August 2008
- July 2008
- June 2008
- May 2008
Recent Comments