Показать сообщение отдельно
Старый 19.11.2010, 00:51   #1  
Dicora is offline
Dicora
Участник
 
109 / 15 (1) ++
Регистрация: 12.07.2010
Вытащить приаттаченные файлы из CRM по запросу
Такой вопрос,

в 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="&amp;CRMWRPCToken=e0GDXOMxEd%2b7cAAwSL5zLYi1nc0zLu8zyT7PKCtqj%2bgRbiPPRbvx5t1VVY8eEVZl&amp;CRMWRPCTokenTimeStamp=634257120771013998"><img alt="" src="/_imgs/attachments/16_generic.gif" align="absmiddle" border="0">&nbsp;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 по запросу?

Заранее спасибо!