none
CRM пользователь внутри плагина RRS feed

  • Вопрос

  • Добрый день, уважаемые эксперты.
    Уже несколько раз задавал подобные вопросы. Но все равно, когда дошло до внедрения плагина остались не понятные вопросы.

    Я делаю плагин для Ms CRM.
    Внутри своего плагина определяю под каким пользователем была произведена авторизация.
                        WhoAmIRequest userReq = new WhoAmIRequest();
                            lblDebug.Text += "(WhoAmIResponse)service.Execute(userReq) <br/>";
                            WhoAmIResponse resp = (WhoAmIResponse)service.Execute(userReq);

                            lblDebug.Text += "QueryExpression <br/>";
                            QueryExpression qExp = new QueryExpression();
                            lblDebug.Text += "QueryByAttribute <br/>";
                            QueryByAttribute qByAt = new QueryByAttribute();
                            lblDebug.Text += "ColumnSet <br/>";
                            qByAt.ColumnSet = new AllColumns();
                            lblDebug.Text += "EntityName "+ EntityName.incident.ToString()+"<br/>";
                            qByAt.EntityName = EntityName.incident.ToString();
                            lblDebug.Text += "qByAt.Attributes = new string[] { \"ownerid\" }; <br/>";
                            qByAt.Attributes = new string[] { "ownerid" };
                            lblDebug.Text += "qByAt.Values = new string[] { resp.UserId.ToString() }; <br/>";
                            qByAt.Values = new string[] { resp.UserId.ToString() };

    У меня возвращается пользователь SYSTEM, а не тот пользователь, под которым авторизовались в CRM. Хотя и не совсем понятно как должен вернуться пользователь CRM, ведь плагин это отдельное приложение, запущенное как отдельная задача IIS.
    Поясните этот момент, пожалуйста?
    Как все-таки получить имя пользователя CRM внутри своего плагина?
    Что не правильно в подходе?

    13 января 2010 г. 9:17

Ответы

  • Вообще то очень странно...

    Решил перепроверить - у меня всё замечательно заработало просто сходу.
    По порядку шаги:
    1. В студии создал новый вебсайт.
    2. Открыл web.config данного вебсайта и заменил его содержимое на следующее:

    <?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>
    
    3. Открыл страницу и переисеновал её на UserTest.
    4. Открыл layout страницы и добавли туда метку (asp:Label) и переименовал её на lblUserName.
    5. В Page_Load страницы поместил следующий код:

    		if (string.IsNullOrEmpty(Request.QueryString["orgname"]))
    		{
    			lblUserName.Text = "There are no orgnam parameter in request";
    			return;
    		}
    
    		string orgname = Request.QueryString["orgname"];
    
    		try
    		{
    			using (new CrmImpersonator())
    			{
    				CrmAuthenticationToken token = CrmAuthenticationToken.ExtractCrmAuthenticationToken(Context, orgname);
    
    				CrmService crmservice = new CrmService();
    				crmservice.CrmAuthenticationTokenValue = token;
    				crmservice.UseDefaultCredentials = true;
    				crmservice.Url = (string)(Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\MSCRM").GetValue("ServerUrl")) + "/2007/crmservice.asmx";
    
    				systemuser user = (systemuser)crmservice.Retrieve(EntityName.systemuser.ToString(), token.CallerId, new ColumnSet(new string[] { "fullname" }));
    				lblUserName.Text = string.Format("Your name is - {0}", user.fullname);
    			}
    		}
    		catch (SoapException sexc)
    		{
    			lblUserName.Text = string.Format("Exception occured - {0}", sexc.Detail.InnerText);
    		}
    		catch (Exception ex)
    		{
    			lblUserName.Text = string.Format("Exception occured - {0}", ex.Message);
    		}
    
    6. Сохранил все изменения.
    7. На проекте кликнул правой мыши - Publish Web Site, указал каталог, отметил галочку 'Us fixed naming and single page assemblies'.
    8. Открыл подкаталог ISV веб-сайта CRM, создал в нём каталог usertest.
    9. Открыл созданный каталог и скопировал в него из каталога в который осуществлялся Publish сайта файлы aspx, config.
    10. Открыл подкаталог bin каталога веб-сайта CRM и скопировал в него сборку из подкаталога bin каталога в который осуществлялся Publish сайта.

    Результат .
    Truth is opened the prepared mind

    My blog (english)
    Мой блог (русскоязычный)free countersLocations of visitors to this page
    18 января 2010 г. 13:59

Все ответы

  • А не проще ли получить идентификатор пользователя вот так:

    Guid userid = context.UserId;

    И далее уже использовать данный идентификатор для получения имени.

    Truth is opened the prepared mind

    My blog (english)
    Мой блог (русскоязычный) free counters Locations of visitors to this page
    13 января 2010 г. 9:51

  • Добрый день.
    Спасибо Вам большое за ответы.

    У нас ни один из способов определения пользователя внутри плагина (в том числе и тот что Вы указываете), под которым вошли в CRM не работает.
    Есть подозрение, что мы не правильно инсталлируем свой плагин в CRM.

    Поэтому расскажу как делаю, а Вы поправьте, пожалуйста.
    Делаю двумя способами:
    Способ 1.
    Создаю отдельный сайт в IIS на одном сервере с CRM. Использую 83-й порт. CRM размещена на 80-м. Размещаю свой плагин как отдельный сайт. Правлю карту сайта CRM, создаю там новый пункт, и добавляю в карту сайта ссылку на мой плагин http://CRMIPaddress:83/default.aspx.

    Способ 2.
    Кладу свой плагин в папку ISV внутрь папки CRM.
    Далее аналогично правлю сайт и добавляю туда ссылку http://CRMIPaddress/ISV/Test/default.aspx

    Возвращается ошибка:

    Может я не прав?
    Подскажите, пожалуйста, где я не прав?
    15 января 2010 г. 13:12
  • То что Вы назвали Плагином - совсем не плагин. Читайте SDK .
    Truth is opened the prepared mind

    My blog (english)
    Мой блог (русскоязычный)free countersLocations of visitors to this page
    • Предложено в качестве ответа Andrii ButenkoMVP 21 января 2010 г. 11:28
    15 января 2010 г. 13:16
  • Можно ли внутри нашей подсистемы (пусть это будет не плагин а add on) узнать логин пользователя под которым авторизовались в CRM?
    15 января 2010 г. 13:49
  • Получение идентификатора пользователя со страницы, интегрированной в CRM по вашему пункту 2 может быть осуществлено в кодебихайнде таким образом:

    Guid userid = Guid.Empty;
    using (new CrmImpersonator()) { CrmAuthenticationToken token = CrmAuthenticationToken.ExtractCrmAuthenticationToken(Context, OrgName); userid token.CallerId; }
    где OrgName - название организации.

    Из своего опыта скажу, что для нормальной работы страницы из CRM - Web.Config должен иметь примерно следующий вид:
    <?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>
    

    Truth is opened the prepared mind

    My blog (english)
    Мой блог (русскоязычный) free counters Locations of visitors to this page
    15 января 2010 г. 16:02
  • Спасибо большое Вам за ответы.
    Действуем так как Вы написали в предыдущем посте.

    Попробовал добавить в наш web.config в раздел 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"/>

    Приложение падает при подключенных модулях еще до исполнения основного кода.

    Без этих модулей ошибка.

    System.Security.SecurityException:
    UserId not found for the current user on the context at
    Microsoft.Crm.Sdk.CrmAuthenticationToken.InternalGetCallerId(HttpContext
    context) at
    Microsoft.Crm.Sdk.CrmAuthenticationToken.ExtractCrmAuthenticationToken(HttpContext
    context, String orgName) at TimeSheet._Default.BindData() The Zone of
    the assembly that failed was: MyComputer

    Подскажите в чем может быть причина падения?
    Что делаем не так опять?
    18 января 2010 г. 9:40
  • Веб конфиг чего Вы правили? Если веб конфиг самого CRM, то так поступать нельзя...

    Плюс откуда пытаетесь вызвать страницу? Если из студии, то работать оно не будет. Страницу надо скопировать в какой нибудь подкаталог ISV каталога CRM и уже запускать оттуда.
    Truth is opened the prepared mind

    My blog (english)
    Мой блог (русскоязычный)free countersLocations of visitors to this page
    18 января 2010 г. 9:46
  • правили web.config нашего приложения.
    Приложение было размещено в ISV\<appname>
    в IIS был создан новый сайт, на который сделана ссылка с помощью sitemap.
    Application pool был Default, а у CRM свой app pool отдельный.
    18 января 2010 г. 9:59
  • Вы можете еще что-то подсказать здесь? Почему подсистема может падать подключения вышеуказанных модулей?
    18 января 2010 г. 11:57
  • Вообще то очень странно...

    Решил перепроверить - у меня всё замечательно заработало просто сходу.
    По порядку шаги:
    1. В студии создал новый вебсайт.
    2. Открыл web.config данного вебсайта и заменил его содержимое на следующее:

    <?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>
    
    3. Открыл страницу и переисеновал её на UserTest.
    4. Открыл layout страницы и добавли туда метку (asp:Label) и переименовал её на lblUserName.
    5. В Page_Load страницы поместил следующий код:

    		if (string.IsNullOrEmpty(Request.QueryString["orgname"]))
    		{
    			lblUserName.Text = "There are no orgnam parameter in request";
    			return;
    		}
    
    		string orgname = Request.QueryString["orgname"];
    
    		try
    		{
    			using (new CrmImpersonator())
    			{
    				CrmAuthenticationToken token = CrmAuthenticationToken.ExtractCrmAuthenticationToken(Context, orgname);
    
    				CrmService crmservice = new CrmService();
    				crmservice.CrmAuthenticationTokenValue = token;
    				crmservice.UseDefaultCredentials = true;
    				crmservice.Url = (string)(Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\MSCRM").GetValue("ServerUrl")) + "/2007/crmservice.asmx";
    
    				systemuser user = (systemuser)crmservice.Retrieve(EntityName.systemuser.ToString(), token.CallerId, new ColumnSet(new string[] { "fullname" }));
    				lblUserName.Text = string.Format("Your name is - {0}", user.fullname);
    			}
    		}
    		catch (SoapException sexc)
    		{
    			lblUserName.Text = string.Format("Exception occured - {0}", sexc.Detail.InnerText);
    		}
    		catch (Exception ex)
    		{
    			lblUserName.Text = string.Format("Exception occured - {0}", ex.Message);
    		}
    
    6. Сохранил все изменения.
    7. На проекте кликнул правой мыши - Publish Web Site, указал каталог, отметил галочку 'Us fixed naming and single page assemblies'.
    8. Открыл подкаталог ISV веб-сайта CRM, создал в нём каталог usertest.
    9. Открыл созданный каталог и скопировал в него из каталога в который осуществлялся Publish сайта файлы aspx, config.
    10. Открыл подкаталог bin каталога веб-сайта CRM и скопировал в него сборку из подкаталога bin каталога в который осуществлялся Publish сайта.

    Результат .
    Truth is opened the prepared mind

    My blog (english)
    Мой блог (русскоязычный)free countersLocations of visitors to this page
    18 января 2010 г. 13:59
  • Спасибо большое  здесь мы разобрались.
    Осталась одна проблема в нашем add-on в CRM

    В веб-сайте add-on'е для CRM используется стандартный GridView для
    отображения информации

    Чтобы выделять строку в этом gridview по щелчку на ней, делаем следующее

            protected void gv_RowDataBound(object sender,
    GridViewRowEventArgs e)
            {
                if (e.Row.RowType == DataControlRowType.DataRow)
                {
                    e.Row.Attributes.Add("onclick",
    Page.ClientScript.GetPostBackEventReference((System.Web.UI.Control)sender,
    "Select$" + e.Row.RowIndex.ToString()));
                }
            }


    Запускаем локально - все работает.

    Размещаем проект в <crmwebroot>\ISV\test
    файлы из bin размещаем в <crmwebroot>\bin , в соответствии с
    рекомендациями в ветке
    http://social.technet.microsoft.com/Forums/ru-RU/dynamicsru/thread/74e7c0bf-decb-43bf-bd2f-606cdb108aef

    Запускаем, таблица сначала загружается с нужными данными, но при щелчке
    на строке, gridview полностью пропадает.

    Почему так происходит?
    Как сделать корректное выделение элемента в GridView?
    20 января 2010 г. 14:31
  • Рекомендую пользоваться JavaScript, поскольку уже не единоразово замечал, что стандартные казалось бы для asp.net конструкции некорректно работают.
    Truth is opened the prepared mind

    My blog (english)
    Мой блог (русскоязычный)free countersLocations of visitors to this page
    20 января 2010 г. 14:45
  • Так мы здесь и пользуемся Javascript
    function __doPostBack(eventTarget, eventArgument) {
        if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
            theForm.__EVENTTARGET.value = eventTarget;
            theForm.__EVENTARGUMENT.value = eventArgument;
            theForm.submit();
        }
    }

    а __doPostBack стандартная функция добавляемая в страницу asp.net'ом


    Как по другому выделить элемент в GridView через JavaScript я не знаю?
    Или я не понял ответ?
    Это может быть связано с настройкой сервера CRM? Потому что локальная копия работает нормально под отладчиком, а не работает, та что размещена на сервере CRM

    20 января 2010 г. 15:42
  • Я немного знаком с asp.net и знаю слегка как и что asp.net добавляет на страницу. Имел я ввиду выделение написанное самостоятельно, а не скриптами, которые нагенерирует сам asp.net. Как в такой ситуации поступить сходу не скажу - тут надо экспериментировать.

    Truth is opened the prepared mind

    My blog (english)
    Мой блог (русскоязычный)free countersLocations of visitors to this page
    20 января 2010 г. 15:54
  • Спасибо большое за Ваши подсказки.
    Со всем этим вроде бы разобрались.
    Остался еще только такой вопрос.
    Мы работаем с CASE через sdk. Класс incident.
    http://msdn.microsoft.com/en-us/library/bb956649.aspx
    Как используя методы и свой-ва данного класса, определить, что CASE находится в состоянии Active?
    А не закрыт.
    21 января 2010 г. 8:59
  • В данном классе есть свойства statecode и statuscode - их комбинация даст Вам полную информацию о состоянии Case. Ознакомьтесь со следующей ссылкой - http://msdn.microsoft.com/en-us/library/bb959325.aspx

    Truth is opened the prepared mind

    My blog (english)
    Мой блог (русскоязычный)free countersLocations of visitors to this page
    • Предложено в качестве ответа Andrii ButenkoMVP 21 января 2010 г. 11:28
    21 января 2010 г. 9:54
  • Спасибо Вам за помощь.
    21 января 2010 г. 10:32