Some time when you use SPUtility.SendEmail method you may get “Operation is not valid due to the current state of the object” error:
at Microsoft.SharePoint.WebControls.SPControl.SPWebEnsureSPControl(HttpContext context)
at Microsoft.SharePoint.WebControls.SPControl.GetContextWeb(HttpContext context)
at Microsoft.SharePoint.WebControls.SPControl.GetContextSite(HttpContext context)
at Microsoft.SharePoint.MailMessage.set_Body(String value)
at Microsoft.SharePoint.Utilities.SPUtility.SendEmail(SPWeb web, Boolean fAppendHtmlTag, Boolean fHtmlEncode, String to, String subject, String htmlBody, Boolean appendFooter)
at Microsoft.SharePoint.Utilities.SPUtility.SendEmail(SPWeb web, Boolean fAppendHtmlTag, Boolean fHtmlEncode, String to, String subject, String htmlBody)
It may occur e.g. when you use this method from web service. Let’s check the implementation of this method:
1: public static bool SendEmail(SPWeb web, bool fAppendHtmlTag,
2: bool fHtmlEncode, string to, string subject, string htmlBody, bool appendFooter)
3: {
4: MailMessage message = new MailMessage(fAppendHtmlTag, fHtmlEncode);
5: message.Web = web;
6: if (to != null)
7: {
8: message.To = to;
9: }
10: message.From = string.Empty;
11: if (subject != null)
12: {
13: message.Subject = subject;
14: }
15: if (htmlBody != null)
16: {
17: message.Body = htmlBody;
18: }
19: message.AppendEmailFooter = appendFooter;
20: return message.FSend();
21: }
According to stack trace error comes from line 17 when assigning body to MailMessage. Property setter set_Body() uses SPControl.GetContextSite(…) method which causes the error:
1: public virtual void set_Body(string value)
2: {
3: if (string.Compare(this.m_md.strContentType, "text/html", true,
4: CultureInfo.InvariantCulture) != 0)
5: {
6: this.m_md.strHTMLBody = value;
7: }
8: else
9: {
10: string str;
11: SPWeb contextWeb;
12: if (!this.m_fHtmlEncode)
13: {
14: str = value;
15: }
16: else
17: {
18: str = SPHttpUtility.HtmlEncodeAllowSimpleTextFormatting(value);
19: }
20: HttpContext current = HttpContext.Current;
21: if (current == null)
22: {
23: SPSite site = this.Web.Site;
24: contextWeb = this.Web;
25: }
26: else
27: {
28: SPControl.GetContextSite(current);
29: contextWeb = SPControl.GetContextWeb(current);
30: }
31: if (((((ushort) contextWeb.Language) & 0x3ff) == 1) || (((ushort) contextWeb.Language) == 0x40d))
32: {
33: str = "<DIV dir=rtl>" + str + "</DIV>";
34: }
35: if (this.m_fAppendHtmlTag)
36: {
37: this.m_md.strHTMLBody =
38: "<HTML><HEAD><META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html\"></HEAD><BODY>" +
39: str + "</BODY></HTML>";
40: }
41: else
42: {
43: this.m_md.strHTMLBody = str;
44: }
45: this.m_fReset = true;
46: }
47: }
When call is performed outside of control and any UI components the mentioned exception is thrown. As you can see in the code (lines 20-30) it checks HttpContext.Current. So in order to fix the error you may use the following workaround:
1: var ctx = HttpContext.Current;
2: try
3: {
4: HttpContext.Current = null;
5: SPUtility.SendEmail(...);
6: }
7: finally
8: {
9: HttpContext.Current = ctx;
10: }
After that inside MailMessage.set_Body() method another lines will be used for initialization of contextWeb variable (line 23-24) and error will disappear.
Thanks Alex, You Saved my Day :)
ReplyDeletebeautiful :) thanks
ReplyDeleteThis fixed my problem when adding a sharepoint site with wfc
ReplyDelete