Такой вопрос,
в CRM в примечаниях можно вкладывать вложения, после чего они сохраняются в таблице AnnotationBase. Что характерно как-то странно они там сохраняются т.к. непонятно в базе они хранятся или на сервере.
Мои предположения где может храниться файл:
На сервере
В этом случае в базе в таблице в одной из колонок должна быть сохранена ссылка на файл или его идентификатор чтобы можно было его потом найти и подгрузить.
Облазил всю базу CRM и не нашел ни одной ссылки. кроме 2х интересных полей:
MimeType, DocumentBody
Причем хочу заметить что если в MimeType заголовок файла сохранен, то в DocumentBody содержимое файла не сохранено, т.к. если бы содержимое всех файлов в закодированном виде хранилось в этой колонке тип её был бы как минимум BLOB, а длинна содержимого различных файлов (по размеру) должна отличаться.
Содержимое же колонки DocumentBody для файлов разных размеров одинаковое (по длинне символов) что наводит на странные мысли. Значит это ссылка либо какой-то идентификатор. Вопрос какой? и где его применить?
Идем дальше..
Открыл форму с примечаниям (точнее код IFRAME содержащее примечания) с вложенным файлом и через IE Developer ToolBar выцепляю код слоя с фалом примечания, т.к. при клике у меня открывается файл - значит истоки места откуда эти файлы скачиваются нужно здесь.
Нахожу такой код
X++:
<span class="attachment" title="Щелкните для открытия" attachmentId="{FF896FAA-59F3-DF11-BB70-003048BE732D}" attachmentType="5" merchantId="{E07FE863-0126-DF11-A3C0-003048BE732D}" userId="{A0CB17C4-AD26-DF11-9050-003048BE732D}" url="/OrgName/Activities/Attachment/download.aspx"" WRPCTokenUrl="&CRMWRPCToken=e0GDXOMxEd%2b7cAAwSL5zLYi1nc0zLu8zyT7PKCtqj%2bgRbiPPRbvx5t1VVY8eEVZl&CRMWRPCTokenTimeStamp=634257120771013998"><img alt="" src="/_imgs/attachments/16_generic.gif" align="absmiddle" border="0"> 833.rtf</span><span class="ms-crm-Attachment-SizeSpacer"></span>
где нужно обратить внимание на следующее:
1) Путь к странице с которой скачиваются файлы:
/OrgName/Activities/Attachment/download.aspx - уже хорошо.
Осталось определиться с параметрами которые нужно передать на этот скрипт, чтобы получить файл:
2) Напрашивается GUID примечания (AnnotationId) из таблицы AnnotationBase
{FF896FAA-59F3-DF11-BB70-003048BE732D} в форме аттрибут AttachmentId
3) Также Тип объекта (по нашему сущности в примечании которой мы работаем)
5 (колонка ObjectTypeCode из этой же таблицы) в форме аттрибут AttachmentType
4) GUID Пользователя (либо того который открывает примечание либо того кто его создал), в данном случае в обеих ролях выступаю я один поэтому это сейчас не важно:
{A0CB17C4-AD26-DF11-9050-003048BE732D} в базе Колонка OwningUser в форме аттрибут UserId
5) за что отвечает аттрибут merchantId на форме - я так и не разобраля, т.к. GUID объекта сущности организации по отношению к которой я создавал примечание отличается от всех GUID-ов используемых в форме.
6) Два неизвестных аттрибута:
а) CRMWRPCToken=e0GDXOMxEd%2b7cAAwSL5zLYi1nc0zLu8zyT7PKCtqj%2bgRbiPPRbvx5t1VVY8eEVZl
б) CRMWRPCTokenTimeStamp=634257120771013998
Как они генерируются и где используюся мне понять не удалось.
Теперь собственно развязка:
Если запустить этот URL и передать в него все эти параметры - файл не открывается!!! Т.е. Алгоритм и механизм по которой по клику на вложенный файл в примечании CRM выдает закачанный файл для скачки - не понятен.
Также не понятно как генерировать эти Токены в случае если нужно создать страницу, в которую хотелось бы передавать просто GUID аннотации (примечания) и чтобы в ответ предлагалось скачать файл.
Похожее решение я нашел вот тут:
http://mmcrm.ru/?p=1138
Я не буду цитировать весь код, только важную инфу:
Нужен этот код:
X++:
using System;
using System.Configuration;
using System.Data;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.Sdk.Query;
using Microsoft.Crm.SdkTypeProxy;
using System.Net;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Web.Services.Protocols;
using Microsoft.Win32;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
try
{
// Выполняем код под юзвером открывашем страницу
using (new CrmImpersonator())
{
// Проверяем что через URL передан параметр guid, иначе прекращаем выполнение
if (Request.QueryString["guid"] == null) return;
// Настраиваем CRM Service
CrmAuthenticationToken token = CrmAuthenticationToken.ExtractCrmAuthenticationToken(Context, "superfirma");
CrmService service = new CrmService();
service.CrmAuthenticationTokenValue = token;
service.UseDefaultCredentials = true;
// Вытаскиваем имя СRM сервера из регистра Windows
service.Url = (string)(Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\MSCRM").GetValue("ServerUrl")) + "/2007/crmservice.asmx";
// Кэшируем credentials, чтобы каждый запрос не проходил повторно аутентификацию
service.PreAuthenticate = true;
// Запрашиваем примечание с GUID'ом переданным через URL
Guid annotationId = new Guid(Request.QueryString["guid"]);
// Нам нужны следующие колонки: имя файла, содержимое файло и его тип
ColumnSet cols1 = new ColumnSet();
cols1.Attributes.Add("filename");
cols1.Attributes.Add("documentbody");
cols1.Attributes.Add("mimetype");
// Отправляем запрос в CRM Service
annotation annotationAttachment = (annotation)service.Retrieve(EntityName.annotation.ToString(), annotationId, cols1);
// Перекодируем содержимое файла хранящееся в БД CRM из кодировки Base64 в byte...
byte[] fileContent = Convert.FromBase64String(annotationAttachment.documentbody);
// ... а из byte в string
string s = System.Text.Encoding.Default.GetString(fileContent);
// Обнуляем изначальный ответ и возвращяем ответ в виде файла
Response.ClearContent();
Response.AddHeader("content-disposition", "attachment; filename=" + annotationAttachment.filename);
Response.ContentType = annotationAttachment.mimetype;
Response.BinaryWrite(fileContent);
Response.End();
}
}
catch (SoapException sexc)
{
throw new Exception(sexc.Detail.InnerText);
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
}
по мнению автора если передать в этот скрипт GUID вернуться должен приаттаченный файл, я создал в корневой папке этот скрипт. Передаю туда GUID влоенного файла в CRM и получаю ошибку - файл не скачиваетя.
Возможно из-за неверных настроек web.config, т.к. из статьи не понятно каким образом нужно внести эти добавления в существующий конфиг, всё удалить и вставить этот маленький кусочек:
X++:
<?xml version="1.0"?>
<configuration>
<appSettings/>
<connectionStrings/>
<system.web>
<httpModules>
<add name="MapOrg" type="Microsoft.Crm.MapOrgEngine, Microsoft.Crm, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
<add name="CrmAuthentication" type="Microsoft.Crm.Authentication.AuthenticationEngine, Microsoft.Crm, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</httpModules>
<identity impersonate="true"/>
<compilation debug="true">
<assemblies>
<add assembly="Microsoft.Crm.Sdk, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add assembly="Microsoft.Crm.SdkTypeProxy, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
</assemblies>
</compilation>
</system.web>
</configuration>
или куда то в особенное место нужно это поставить - непонятно. Возможно ошибки из-за этого.
Подскажите пожалуйста как мне решить эту задачу с выгрузкой приаттаченных файлов из CRM по запросу?
Заранее спасибо!