Outlook 2010 Addon - MailItem.ReplyAll with original body - c#

I'm trying to create a small Addin, which should help me to create a Standard-Email for support-cases.
My procedure is looking like this:
private static void CreateAnswer(MailItem item, int pbiId, SupportType st)
{
MailItem answer = item.ReplyAll();
answer.Subject = String.Concat(String.Format("[{0}] ", pbiId), answer.Subject);
Recipient rec = answer.Recipients.Add("Test");
rec.Type = (int)OlMailRecipientType.olCC;
rec.Resolve();
answer.BodyFormat = OlBodyFormat.olFormatHTML;
string ressourceFile = String.Format("OutlookExtender2.{0}.html", st.ToString());
Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(ressourceFile);
StreamReader sr = new StreamReader(stream);
string text = sr.ReadToEnd();
string[] senderParts = item.SenderName.Split(' ');
string rawOrigBody = GetRawHtmlBody(item.HTMLBody);
string htmlBody = ReplaceBodyText(text, senderParts.Last(), pbiId);
htmlBody = htmlBody.Insert(htmlBody.IndexOf("</body>"), rawOrigBody);
answer.HTMLBody = htmlBody;
answer.Importance = MapImportanceToSupportType(st);
answer.Display(false);
}
Nothing to fancy here, but I'd really like to have the standard-answer with the header (From, Sent, To etc.)
As you can see I'm reading out manually the original text and add it, but this isn't working very well. Is there a possibility to make use of the outlook standard function "ReplyAll", which creates the desired original message?
So the original message should look like this (Sent from my private address):
Von: "Matthias Müller" [mailto:testekituks#gmx.ch]
Gesendet: Mittwoch, 26. Februar 2014 14:48
An: Matthias Müller
Betreff: test from gmx
test from gmx
Probably in english or german, doesn't matter that much.
Is there a possibility to let Outlook do this stuff?
Matthias

I don't quite follow what you are trying to do. Do you want to initialize a template with set content whenever you Reply All to a message? So that the body has + ?

Related

get the undeliverable email address with mimekit/mailkit library

I started using #jstedfast Mimekit/Mailkit library, which is great by the way, to pull undeliverables using its subject line for search. I tried using the message.to, message.resentto.
how do i get that information. My first try today. I was able to get the list and the body but I just need the email. I tried using s22.imap but there's no support anymore then I discovered this. I know you're active here #jstedfast I need you help..there's no discussion tab in your github.
Thanks in advance
If you look at the raw message source, does the value of the Content-Type header match something along the lines of multipart/report; report-type=delivery-status? If so, it is very likely that this message will have a sub-part with a Content-Type header with a value of message/delivery-status. It should be the second child part of the multipart/report (the first part should be a human-readable explanation).
If so, you can cast the message/delivery-status MimeEntity to an instance of a MessageDeliveryStatus. You'll notice that the MessageDeliveryStatus class has a property called StatusGroups which is a list of multiple collections of headers (e.g. a list of HeaderList objects).
Each HeaderList contains information about a particular recipient that failed. I think what you want to do is look at the Final-Recipient header which will contain 2 pieces of information:
The address-type (should typically be "rfc822")
The mailbox of the recipient (which is what you want)
Unfortunately, MimeKit does not have any tools to parse the Final-Recipient header, but it should be trivial to locate the end of the address-type parameter in the header value by using IndexOf (';') and then you can use something like MailboxAddress.TryParse() to parse it (or you could probably just Substring() the value w/o parsing).
So, the way this might look in code is this:
string[] GetUndeliverableAddresses (MimeMessage message)
{
var report = message.Body as MultipartReport;
if (report == null)
throw new ArgumentException ("This is not a multipart/report!");
MessageDeliveryStatus status = null;
for (int i = 0; i < report.Count; i++) {
status = report[i] as MessageDeliveryStatus;
if (status != null)
break;
}
if (status == null)
throw new ArgumentException ("Did not contain a message/delivery-status!");
var undeliverables = new List<string> ();
for (int i = 0; i < status.StatusGroups.Count; i++) {
var recipient = status.StatusGroups[i]["Final-Recipient"];
int semicolon = recipient.IndexOf (';');
var undeliverable = recipient.Substring (semicolon + 1).Trim ();
undeliverables.Add (undeliverable);
}
return undeliverables.ToArray ();
}
For more information on message/delivery-status, see https://www.rfc-editor.org/rfc/rfc3464
Hope that helps.
this is what I did
foreach (var uid in inbox.Search(query))
{
var message = inbox.GetMessage(uid);
// Console.WriteLine("Subject: {0}", message.Subject);
//Console.WriteLine("Subject: {0}", message.Headers);
// Console.WriteLine("Subject: {0}", message.BodyParts);
var text = message.BodyParts;
string src = text.ElementAt(1).ToString();
int srcStart = src.IndexOf("RFC822;",0); << i used final-recipient intially
int srcEnd = src.IndexOf("Action", 0);
Console.WriteLine("Email:" + src.Substring(srcStart + 8, srcEnd - (srcStart + 8)));
Console.WriteLine(src);
//foreach (var part in message.BodyParts)
//{
// Console.WriteLine(part);
// // do something
//}
}
let me know if there could be a problem..will I get the rfc822 if the recipient inbox is full? there's no way i can test that.. I tested with emails with nonexistent domain, mailbox does not exist..with live.com, randomdomain.com,yahoo.com and gmail. gmail, on the other hand does not return any undeliverables.

HTTP POST read response as regular string

I am currently doing a API HTTP POST project.
I should be getting
"[{\"ID\":\"311d1977-4772-435a-92aa-028791c53154\",\"ParentID\":\"187a064e-ffea-45a2-9264-9acecff911e1\",\"Type\":\"txt\",\"OwnerID\":\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\",\"Name\":\"Davinshi.txt\",\"CreatedBy\":\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\",\"CreatedDate\":\"2015-06-05T04:11:33.187\",\"Status\":0,\"Mark\":null},{\"ID\":\"25c80f4e-679c-4093-ade9-0b99da480153\",\"ParentID\":\"187a064e-ffea-45a2-9264-9acecff911e1\",\"Type\":\"jpg\",\"OwnerID\":\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\",\"Name\":\"leonid afremov.jpg\",\"CreatedBy\":\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\",\"CreatedDate\":\"2015-06-05T04:11:46.61\",\"Status\":0,\"Mark\":null}
However with the follow code I am getting a weird output
using (var client = new WebClient())
{
var val = new NameValueCollection();
foreach (var item in values)
{
val.Add(item.Key, item.Value);
}
var response = client.UploadValues(url, val);
return Encoding.Default.GetString(response);
}
This is the output
\"[{\\\"ID\\\":\\\"311d1977-4772-435a-92aa-028791c53154\\\",\\\"ParentID\\\":\\\"187a064e-ffea-45a2-9264-9acecff911e1\\\",\\\"Type\\\":\\\"txt\\\",\\\"OwnerID\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"Name\\\":\\\"Davinshi.txt\\\",\\\"CreatedBy\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"CreatedDate\\\":\\\"2015-06-05T04:11:33.187\\\",\\\"Status\\\":0,\\\"Mark\\\":null},{\\\"ID\\\":\\\"25c80f4e-679c-4093-ade9-0b99da480153\\\",\\\"ParentID\\\":\\\"187a064e-ffea-45a2-9264-9acecff911e1\\\",\\\"Type\\\":\\\"jpg\\\",\\\"OwnerID\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"Name\\\":\\\"leonid afremov.jpg\\\",\\\"CreatedBy\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"CreatedDate\\\":\\\"2015-06-05T04:11:46.61\\\",\\\"Status\\\":0,\\\"Mark\\\":null},{\\\"ID\\\":\\\"5648cc67-1408-4935-a656-0f9b5116db8d\\\",\\\"ParentID\\\":\\\"187a064e-ffea-45a2-9264-9acecff911e1\\\",\\\"Type\\\":\\\"jpg\\\",\\\"OwnerID\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"Name\\\":\\\"misty mood leonid.jpg\\\",\\\"CreatedBy\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"CreatedDate\\\":\\\"2015-06-05T04:11:49.437\\\",\\\"Status\\\":0,\\\"Mark\\\":null},{\\\"ID\\\":\\\"7402e7b8-1ec4-4bf8-9042-142a69cecbcd\\\",\\\"ParentID\\\":\\\"187a064e-ffea-45a2-9264-9acecff911e1\\\",\\\"Type\\\":\\\"jpg\\\",\\\"OwnerID\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"Name\\\":\\\"winter sparkle.jpg\\\",\\\"CreatedBy\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"CreatedDate\\\":\\\"2015-06-05T04:12:03.26\\\",\\\"Status\\\":0,\\\"Mark\\\":null},{\\\"ID\\\":\\\"7159e926-1601-41d6-8dce-20e5daab90a6\\\",\\\"ParentID\\\":\\\"187a064e-ffea-45a2-9264-9acecff911e1\\\",\\\"Type\\\":\\\"txt\\\",\\\"OwnerID\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"Name\\\":\\\"gentle rain beata sasik.txt\\\",\\\"CreatedBy\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"CreatedDate\\\":\\\"2015-06-05T04:11:40.6\\\",\\\"Status\\\":0,\\\"Mark\\\":null},{\\\"ID\\\":\\\"e61f7bc4-bebf-403b-a478-22b36856a6df\\\",\\\"ParentID\\\":\\\"187a064e-ffea-45a2-9264-9acecff911e1\\\",\\\"Type\\\":\\\"jpg\\\",\\\"OwnerID\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"Name\\\":\\\"MoonLight.jpg\\\",\\\"CreatedBy\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"CreatedDate\\\":\\\"2015-06-05T04:11:50.797\\\",\\\"Status\\\":0,\\\"Mark\\\":null},{\\\"ID\\\":\\\"e46e6250-655b-4105-a888-2574750f2944\\\",\\\"ParentID\\\":\\\"187a064e-ffea-45a2-9264-9acecff911e1\\\",\\\"Type\\\":\\\"jpg\\\",\\\"OwnerID\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"Name\\\":\\\"blue fire.jpg\\\",\\\"CreatedBy\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"CreatedDate\\\":\\\"2015-06-05T04:11:27.037\\\",\\\"Status\\\":0,\\\"Mark\\\":null},{\\\"ID\\\":\\\"bfca703b-1720-4a67-b0a4-2f6146c820aa\\\",\\\"ParentID\\\":null,\\\"Type\\\":\\\"folder\\\",\\\"OwnerID\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"Name\\\":\\\"School\\\",\\\"CreatedBy\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"CreatedDate\\\":\\\"2015-06-05T04:11:17.96\\\",\\\"Status\\\":0,\\\"Mark\\\":null},{\\\"ID\\\":\\\"5c1bf9ca-b368-46c8-9804-3254eda00806\\\",\\\"ParentID\\\":\\\"187a064e-ffea-45a2-9264-9acecff911e1\\\",\\\"Type\\\":\\\"txt\\\",\\\"OwnerID\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"Name\\\":\\\"Woman.txt\\\",\\\"CreatedBy\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"CreatedDate\\\":\\\"2015-06-05T04:12:06.607\\\",\\\"Status\\\":0,\\\"Mark\\\":null},{\\\"ID\\\":\\\"8ad07f3c-7a57-4add-92c0-329aca372c8b\\\",\\\"ParentID\\\":\\\"187a064e-ffea-45a2-9264-9acecff911e1\\\",\\\"Type\\\":\\\"jpg\\\",\\\"OwnerID\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"Name\\\":\\\"intimacy worship.jpg\\\",\\\"CreatedBy\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"CreatedDate\\\":\\\"2015-06-05T04:11:40.727\\\",\\\"Status\\\":0,\\\"Mark\\\":null},{\\\"ID\\\":\\\"ac5384c4-66ca-45cd-99f0-437c0789a26a\\\",\\\"ParentID\\\":\\\"187a064e-ffea-45a2-9264-9acecff911e1\\\",\\\"Type\\\":\\\"txt\\\",\\\"OwnerID\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"Name\\\":\\\"Under the Rain.txt\\\",\\\"CreatedBy\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"CreatedDate\\\":\\\"2015-06-05T04:12:01.007\\\",\\\"Status\\\":0,\\\"Mark\\\":null},{\\\"ID\\\":\\\"aa731f04-cc4e-4349-9268-4476ff04b473\\\",\\\"ParentID\\\":\\\"bfca703b-1720-4a67-b0a4-2f6146c820aa\\\",\\\"Type\\\":\\\"folder\\\",\\\"OwnerID\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"Name\\\":\\\"Marsiling Secondary School\\\",\\\"CreatedBy\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"CreatedDate\\\":\\\"2015-06-05T04:11:20.983\\\",\\\"Status\\\":0,\\\"Mark\\\":null},{\\\"ID\\\":\\\"af650810-0538-432e-8bf3-47429eb17d27\\\",\\\"ParentID\\\":\\\"187a064e-ffea-45a2-9264-9acecff911e1\\\",\\\"Type\\\":\\\"jpg\\\",\\\"OwnerID\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"Name\\\":\\\"finger paintings.jpg\\\",\\\"CreatedBy\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"CreatedDate\\\":\\\"2015-06-05T04:11:35.65\\\",\\\"Status\\\":0,\\\"Mark\\\":null},{\\\"ID\\\":\\\"ddac31de-2b67-4f56-aefd-508a8f49926f\\\",\\\"ParentID\\\":\\\"187a064e-ffea-45a2-9264-9acecff911e1\\\",\\\"Type\\\":\\\"txt\\\",\\\"OwnerID\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"Name\\\":\\\"My Love.txt\\\",\\\"CreatedBy\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"CreatedDate\\\":\\\"2015-06-05T04:11:56.55\\\",\\\"Status\\\":0,\\\"Mark\\\":null},{\\\"ID\\\":\\\"f2454474-d834-4bd1-992e-548cdc2734c1\\\",\\\"ParentID\\\":\\\"187a064e-ffea-45a2-9264-9acecff911e1\\\",\\\"Type\\\":\\\"txt\\\",\\\"OwnerID\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"Name\\\":\\\"boat.txt\\\",\\\"CreatedBy\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"CreatedDate\\\":\\\"2015-06-05T04:11:28.813\\\",\\\"Status\\\":0,\\\"Mark\\\":null},{\\\"ID\\\":\\\"e1f5be01-29c7-4ca9-ae6f-5ddf8638cc67\\\",\\\"ParentID\\\":\\\"187a064e-ffea-45a2-9264-9acecff911e1\\\",\\\"Type\\\":\\\"jpg\\\",\\\"OwnerID\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"Name\\\":\\\"Davinshi.jpg\\\",\\\"CreatedBy\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"CreatedDate\\\":\\\"2015-06-05T04:11:34.687\\\",\\\"Status\\\":0,\\\"Mark\\\":null},{\\\"ID\\\":\\\"ff3a7365-7b4e-4a46-b545-6a2f889ff898\\\",\\\"ParentID\\\":\\\"187a064e-ffea-45a2-9264-9acecff911e1\\\",\\\"Type\\\":\\\"jpg\\\",\\\"OwnerID\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"Name\\\":\\\"landscape paintings.jpg\\\",\\\"CreatedBy\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"CreatedDate\\\":\\\"2015-06-05T04:11:44.48\\\",\\\"Status\\\":0,\\\"Mark\\\":null},{\\\"ID\\\":\\\"327bf043-1e88-4265-ba5e-6de8394a0d84\\\",\\\"ParentID\\\":\\\"187a064e-ffea-45a2-9264-9acecff911e1\\\",\\\"Type\\\":\\\"jpg\\\",\\\"OwnerID\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"Name\\\":\\\"lord rama.jpg\\\",\\\"CreatedBy\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"CreatedDate\\\":\\\"2015-06-05T04:11:47.753\\\",\\\"Status\\\":0,\\\"Mark\\\":null},{\\\"ID\\\":\\\"1d8a01de-da06-466d-8b7d-6e0bb8478d5e\\\",\\\"ParentID\\\":\\\"187a064e-ffea-45a2-9264-9acecff911e1\\\",\\\"Type\\\":\\\"txt\\\",\\\"OwnerID\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"Name\\\":\\\"intimacy worship.txt\\\",\\\"CreatedBy\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"CreatedDate\\\":\\\"2015-06-05T04:11:41.617\\\",\\\"Status\\\":0,\\\"Mark\\\":null},{\\\"ID\\\":\\\"f23103ec-0d8c-407b-9f20-719f0577c274\\\",\\\"ParentID\\\":\\\"187a064e-ffea-45a2-9264-9acecff911e1\\\",\\\"Type\\\":\\\"jpg\\\",\\\"OwnerID\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"Name\\\":\\\"Coast of Sicily.jpg\\\",\\\"CreatedBy\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"CreatedDate\\\":\\\"2015-06-05T04:11:32.187\\\",\\\"Status\\\":0,\\\"Mark\\\":null},{\\\"ID\\\":\\\"374779d5-16e9-417f-808f-87fcf85035b0\\\",\\\"ParentID\\\":\\\"187a064e-ffea-45a2-9264-9acecff911e1\\\",\\\"Type\\\":\\\"txt\\\",\\\"OwnerID\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"Name\\\":\\\"misty mood leonid.txt\\\",\\\"CreatedBy\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"CreatedDate\\\":\\\"2015-06-05T04:11:54.203\\\",\\\"Status\\\":0,\\\"Mark\\\":null},{\\\"ID\\\":\\\"f0bb2dc7-eac3-407d-a85a-886aaf161fc2\\\",\\\"ParentID\\\":\\\"187a064e-ffea-45a2-9264-9acecff911e1\\\",\\\"Type\\\":\\\"jpg\\\",\\\"OwnerID\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"Name\\\":\\\"boat.jpg\\\",\\\"CreatedBy\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"CreatedDate\\\":\\\"2015-06-05T04:11:28.907\\\",\\\"Status\\\":0,\\\"Mark\\\":null},{\\\"ID\\\":\\\"607ee7b8-7287-4f3f-9867-8a8069562d3c\\\",\\\"ParentID\\\":\\\"187a064e-ffea-45a2-9264-9acecff911e1\\\",\\\"Type\\\":\\\"jpg\\\",\\\"OwnerID\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"Name\\\":\\\"Ballet.jpg\\\",\\\"CreatedBy\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"CreatedDate\\\":\\\"2015-06-05T04:11:24.167\\\",\\\"Status\\\":0,\\\"Mark\\\":null},{\\\"ID\\\":\\\"246b349e-ab32-407a-90ff-8df18bbabc68\\\",\\\"ParentID\\\":\\\"187a064e-ffea-45a2-9264-9acecff911e1\\\",\\\"Type\\\":\\\"txt\\\",\\\"OwnerID\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"Name\\\":\\\"Ballet.txt\\\",\\\"CreatedBy\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"CreatedDate\\\":\\\"2015-06-05T04:11:23.917\\\",\\\"Status\\\":0,\\\"Mark\\\":null},{\\\"ID\\\":\\\"457d722f-a675-4523-bd83-8f309dcd254e\\\",\\\"ParentID\\\":\\\"187a064e-ffea-45a2-9264-9acecff911e1\\\",\\\"Type\\\":\\\"txt\\\",\\\"OwnerID\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"Name\\\":\\\"finger paintings.txt\\\",\\\"CreatedBy\\\":\\\"5bd087f0-070d-48bd-98b4-10ffa4b3b792\\\",\\\"CreatedDate\\\":\\\"2015-06-05T04:11:39.017\\\",\\\"Status\\\":0,\\\
Which I think the HTTP POST Response is reading the string as a verbatim string.
Any idea how can i fix it ?
Thanks !
When I run your code, the output of Encoding.Default.GetString(response) is exactly the string you posted at the top of your question.
The excessively backslash-escaped string appears in the Visual Studio debugging window simply because VS escapes special characters when displaying a string, but if you try to save this string into a file or use it in any other way in your code, you will see that only the double quote marks are escaped, like the string at the top of your question.
I found out that the API will automatically convert the object to json format.
The problem occur when I try to serialize the object before sending trough the API.Hence, like what Denis Yarkovoy said. It's double serialized.

Copying annotations leads to a corrupted attachment

I'm implementing a plugin (POST Quote Create, Synchronous, Sandbox) to make it so that Notes are copied to the new record when a quote is revised.
My plugin boils down to this (snippet):
var serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
var Service = serviceFactory.CreateOrganizationService(context.UserId);
var notesQuery = new QueryExpression("annotation");
notesQuery.ColumnSet = new ColumnSet(true);
notesQuery.Criteria = new FilterExpression
{
FilterOperator = LogicalOperator.And,
Conditions =
{
new ConditionExpression("objecttypecode", ConditionOperator.Equal, "quote"),
new ConditionExpression("objectid", ConditionOperator.Equal, revisedQuoteId)
}
};
var notes = Service.RetrieveMultiple(notesQuery).Entities;
foreach (var n in notes)
{
var newNote = new Entity("annotation");
newNote.Attributes.Add("ownerid", n.GetAttributeValue<EntityReference>("ownerid"));
newNote.Attributes.Add("objectid", new EntityReference("quote", sourceEntity.Id));
newNote.Attributes.Add("objecttypecode", "quote");
newNote.Attributes.Add("subject", n.GetAttributeValue<string>("subject"));
newNote.Attributes.Add("notetext", n.GetAttributeValue<string>("notetext"));
newNote.Attributes.Add("isdocument", n.GetAttributeValue<bool>("isdocument"));
if (n.GetAttributeValue<bool>("isdocument"))
{
newNote.Attributes.Add("filesize", n.GetAttributeValue<int>("filesize"));
newNote.Attributes.Add("documentbody", n.GetAttributeValue<string>("documentbody"));
newNote.Attributes.Add("filename", n.GetAttributeValue<string>("filename"));
newNote.Attributes.Add("mimetype", n.GetAttributeValue<string>("mimetype"));
}
Service.Create(newNote);
}
Basically, I copy everything over, including an eventual attachment. Everything seems fine, the new revision shows fields, detail records and notes properly... everything but the attachment of the notes.
If I have a single note, with an attached test.txt which content is:
Test attachment
The OrganizationData service reads as follows:
<d:FileName>test.txt</d:FileName>
<d:FileSize m:type="Edm.Int32">39</d:FileSize>
<d:DocumentBody>H4sIAAAMaVMA/wtJLS5RSCwpSUzOyE3NK+HlAgCLmj1zEQAAAA==</d:DocumentBody>
Its "clone" has the correct subject and text, and also shows a test.txt attached which content is
‹ iS ÿI-.QH,)ILÎÈMÍ+áå ‹š=s
mimetype and filesize (while checking odata, I noticed that filesize is not actually correct!) appear to be correct (aka: the same as the original note I'm trying to copy), but OData seems to confirm something's off (it's different!):
<d:FileName>test.txt</d:FileName>
<d:FileSize m:type="Edm.Int32">60</d:FileSize
<d:DocumentBody>H4sIAED6aVMA/5Pv5mBg4MkMZvjP7amrF+iho+npc+6E71nth0+ZGLpn2RYLMjAwAABXqCwTJQAAAA==</d:DocumentBody>
The test.txt file was created from a command prompt (COPY CON test.txt, type, CTRL+Z).
I tried to change the file, and created a test.pdf through PDFCreator: AcroRead in turn whines and says the document is corrupted (so it seems like the issue is mimetype-agnostic).
I also tried re-implementing the same code through early binding (via the CRMSVCUTIL-generated classes) but it yields the exact same result (garbage instead of the attachment contents).
I attempted to hand-craft the documentbody like this:
// "VGVzdCBhdHRhY2htZW50" is Base64 for "Test attachment"
newNote.Attributes.Add("documentbody", "VGVzdCBhdHRhY2htZW50");
and the created file is correct.
I can't figure out what's going on: as far as I know, documentbody is supposed to be a Base64-encoded string which (again, as far as I know) shouldn't be any different when copied around. What am I missing ?
For reference, CRM is updated to UR13 but I repro'd it on a UR16 environment.
EDIT: Does NOT work (only for CRM 4)
Try this (not verified):
var notes = Service.RetrieveMultiple(notesQuery).Entities;
foreach (var newNote in notes)
{
newNote.annotationid = null;
newNote.Attributes.Add("objectid", new EntityReference("quote", sourceEntity.Id));
newNote.Attributes.Add("objecttypecode", "quote");
Service.Create(newNote);
}
Just saw this, in an article from MSDN:
Annotation setupAnnotation = new Annotation()
{
Subject = "Example Annotation",
FileName = "ExampleAnnotationAttachment.txt",
DocumentBody = Convert.ToBase64String(
new UnicodeEncoding().GetBytes("Sample Annotation Text")),
MimeType = "text/plain"
};
I see the document body is encoded according to the Unicode encoding. Maybe you should try to retrieve the encoding from the file and convert it to a string accordingly.

Issue in Parsing Json image in C#

net C#. I am trying to parse Json from a webservice. I have done it with text but having a problem with parsing image. Here is the Url from where I m getting Json
http://collectionking.com/rest/view/items_in_collection.json?args=122
And this is My code to Parse it
using (var wc = new WebClient()) {
JavaScriptSerializer js = new JavaScriptSerializer();
var result = js.Deserialize<ck[]>(wc.DownloadString("http://collectionking.com/rest/view/items_in_collection.json args=122"));
foreach (var i in result) {
lblTitle.Text = i.node_title;
imgCk.ImageUrl = i.["main image"];
lblNid.Text = i.nid;
Any help would be great.
Thanks in advance.
PS: It returns the Title and Nid but not the Image.
My class is as follows:
public class ck
{
public string node_title;
public string main_image;
public string nid; }
Your problem is that you are setting ImageUrl to something like this <img typeof="foaf:Image" src="http://... and not an actual url. You will need to further parse main image and extract the url to show it correctly.
Edit
This was a though nut to crack because of the whitespace. The only solution I could find was to remove the whitespace before parsing the string. It's not a very nice solution but I couldn't find any other way using the built in classes. You might be able to solve it properly using JSON.Net or some other library though.
I also added a regular expression to extract the url for you, though there is no error checking what so ever here so you'll need to add that yourself.
using (var wc = new WebClient()) {
JavaScriptSerializer js = new JavaScriptSerializer();
var result = js.Deserialize<ck[]>(wc.DownloadString("http://collectionking.com/rest/view/items_in_collection.json?args=122").Replace("\"main image\":", "\"main_image\":")); // Replace the name "main image" with "main_image" to deserialize it properly, also fixed missing ? in url
foreach (var i in result) {
lblTitle.Text = i.node_title;
string realImageUrl = Regex.Match(i.main_image, #"src=""(.*?)""").Groups[1].Value; // Extract the value of the src-attribute to get the actual url, will throw an exception if there isn't a src-attribute
imgCk.ImageUrl = realImageUrl;
lblNid.Text = i.nid;
}
}
Try This
private static string ExtractImageFromTag(string tag)
{
int start = tag.IndexOf("src=\""),
end = tag.IndexOf("\"", start + 6);
return tag.Substring(start + 5, end - start - 5);
}
private static string ExtractTitleFromTag(string tag)
{
int start = tag.IndexOf(">"),
end = tag.IndexOf("<", start + 1);
return tag.Substring(start + 1, end - start - 1);
}
It may help

Replace tokens in an aspx page on load

I have an aspx page that contains regular html, some uicomponents, and multiple tokens of the form {tokenname} .
When the page loads, I want to parse the page content and replace these tokens with the correct content. The idea is that there will be multiple template pages using the same codebehind.
I've no trouble parsing the string data itself, (see named string formatting, replace tokens in template) my trouble lies in when to read, and how to write the data back to the page...
What's the best way for me to rewrite the page content? I've been using a streamreader, and the replacing the page with Response.Write, but this is no good - a page containing other .net components does not render correctly.
Any suggestions would be greatly appreciated!
Take a look at System.Web.UI.Adapters.PageAdapter method TransformText - generally it is used for multi device support, but you can postprocess your page with this.
I'm not sure if I'm answering your question, but...
If you can change your notation from
{tokenname}
to something like
<%$ ZeusExpression:tokenname %>
you could consider creating your System.Web.Compilation.ExpressionBuilder.
After reading your comment...
There are other ways of getting access to the current page using ExpressionBuilder: just... create an expression. ;-)
Changing just a bit the sample from MSDN and supposing the code of your pages contain a method like this
public object GetData(string token);
you could implement something like this
public override CodeExpression GetCodeExpression(BoundPropertyEntry entry, object parsedData, ExpressionBuilderContext context)
{
Type type1 = entry.DeclaringType;
PropertyDescriptor descriptor1 = TypeDescriptor.GetProperties(type1)[entry.PropertyInfo.Name];
CodeExpression[] expressionArray1 = new CodeExpression[1];
expressionArray1[0] = new CodePrimitiveExpression(entry.Expression.Trim());
return new CodeCastExpression(
descriptor1.PropertyType,
new CodeMethodInvokeExpression(
new CodeThisReferenceExpression(),
"GetData",
expressionArray1));
}
This replaces your placeholder with a call like this
(string)this.GetData("tokenname");
Of course you can elaborate much more on this, perhaps using a "utility method" to simplify and "protect" access to data (access to properties, no special method involved, error handling, etc.).
Something that replaces instead with (e.g.)
(string)Utilities.GetData(this, "tokenname");
Hope this helps.
Many thanks to those that contributed to this question, however I ended up using a different solution -
Overriding the render function as per this page, except I parsed the page content for multiple different tags using regular expressions.
protected override void Render(HtmlTextWriter writer)
{
if (!Page.IsPostBack)
{
using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
{
using (System.IO.StreamWriter streamWriter = new System.IO.StreamWriter(stream))
{
HtmlTextWriter htmlWriter = new HtmlTextWriter(streamWriter);
base.Render(htmlWriter);
htmlWriter.Flush();
stream.Position = 0;
using (System.IO.StreamReader oReader = new System.IO.StreamReader(stream))
{
string pageContent = oReader.ReadToEnd();
pageContent = ParseTagsFromPage(pageContent);
writer.Write(pageContent);
oReader.Close();
}
}
}
}
else
{
base.Render(writer);
}
}
Here's the regex tag parser
private string ParseTagsFromPage(string pageContent)
{
string regexPattern = "{zeus:(.*?)}"; //matches {zeus:anytagname}
string tagName = "";
string fieldName = "";
string replacement = "";
MatchCollection tagMatches = Regex.Matches(pageContent, regexPattern);
foreach (Match match in tagMatches)
{
tagName = match.ToString();
fieldName = tagName.Replace("{zeus:", "").Replace("}", "");
//get data based on my found field name, using some other function call
replacement = GetFieldValue(fieldName);
pageContent = pageContent.Replace(tagName, replacement);
}
return pageContent;
}
Seems to work quite well, as within the GetFieldValue function you can use your field name in any way you wish.

Categories

Resources