Try to work few times before saying “Ups..”

24.11.2010 2 comments

Sometimes it is impossible to give 100% guaranty, that some code will execute properly even if it has realy no mistakes. For example, web service method calls may cause error due to high server load or high concurency in server requests. Programming for MS CRM web services I had faced such situations and here is my solution. Read more…

Categories: C#, MS CRM Tags: ,

Fetch Xml in-memory validation

09.07.2010 Leave a comment

If you need to validate Fetch Xml (or any xml as well) without any external files like .xsd schema, you may find the following code usefull:

        public static Boolean ValidateFetchXml(string fetchxml)
        {
            var reader = new XmlValidatingReader(fetchxml, XmlNodeType.Document, null);
            reader.ValidationType = ValidationType.Schema;
            XmlReader xr = null;
            xr = XmlReader.Create(new MemoryStream(Encoding.Default.GetBytes(schemaText)));
            var schemaCollection = new XmlSchemaCollection();
            schemaCollection.Add(null, xr);
            reader.Schemas.Add(schemaCollection);

            bool isValid = true;
            reader.ValidationEventHandler += ((o, e) => isValid = false);
            reader.Read();

            XmlDocument doc = new XmlDocument();
            try
            {
                doc.LoadXml(fetchxml);
            }
            catch (Exception ex)
            {
                isValid = false;
            }

            return isValid;
        }

Note, that schema name is already loaded into schemaText variable. Its text can be found in CRM SDK in \sdk\server\schemas\fetch.xsd file. As soon as I use it in static class, I’ve made it constant, but you can provide it to method parameters if you will hame different schemas for validation.

Xml-completeness (closed tags) are verified by trying to create XmlDocument. If there are any unclosed tags, it will throw error.

Categories: Data Management, MS CRM, XML Tags: , ,

Creating virtual directories\IIS applications in InstallShield 2008

04.06.2010 1 comment

There is a well-known issue with InstallShield 2008 creating IIS-structure.

The first bad thing in using standard functional of IS (InstallShield) is that it always creates Application on top of every virtual directory, even if you have left a field for application to be blank.

The second is that IS translates application name (if it is really needed) incorrectly. For example, if your application name is stored in String Property named {IIS_VAPP_NAME} and you will see something like this:  {IIS_VAPP_NAME} MyApplication in text box before editing it, then you probably suppose that application will be created with name MyApplication. But its name will be .. “{IIS_VAPP_NAME} MyApplication”.

The third –  if you need to install your site under already existing solution (for example, in ISV virtual folder under Microsoft Dynamics CRM site as in my case), then you’ll need to “create” already existing folder (and it will become application due to the first mentioned IS “feature”) and on uninstall or rollback it will be deleted as configurable object from IIS metabase. Unpleasant, isn’t it?

I really don’t know if more recent versions of IS have these bugs, so this article for those, who has to struggle with InstallShield 2008, like me.

So, what we can do? Read more…

Debugging a web service on production server

01.06.2010 Leave a comment

Browsing the Internet, found an interesting suggestion of how to debug a web service on production server without Visual Studio. “Debug” means ability to run web service with some parameters and check results. To bypass Microsoft security blockhouses it is enough to add following code to the <system.web> section of web.config:

<webServices>
    <protocols>
        <add name="HttpGet"/>
        <add name="HttpPost"/>
    </protocols>
</webServices>

 It will enable input of test parameters when opening an .asmx file.

Source: Ever need to debug a web service from the production server rather than Visual Studio?

Posted just for not forget/lost

Categories: Web Tags: ,

Excel file without Excel installed

01.06.2010 6 comments

Generating xls/xlsx (or just xml, understandable by Excel) on server-side and returning it to users is a very popular task. At least it is very popular in my career. As usual it is done by automating Excel application. Excel API is well documented, there is a possibility to record a macro in Excel and reproduce VBScript in your own code, so development takes minimum time. Read more…

Categories: Excel Tags: ,

Publish Click-Once Application with MSBuild

11.05.2010 7 comments

Задача: Удалить гланды

Ограничение: Через рот нельзя.

Как-то раз мне пришлось публиковать click-once приложение с помощью MSBuid’a. Проект, который нужно публиковать, лежит в TFS’e, в котором настроен автоматический билд. В решении, которое строится билдом – до 50 проектов, одно из которых click-once приложение. Моей задачей было доработать этот билд таким образом, чтобы кроме собственно создания бинарных файлов и опубликованых сайтов, сброшенных в одну кучу, строилась четкая иерархия, которую уже можно было бы “показать” InstallShield’y. В том числе корректно должна выполняться публикация click-once для установки из сети. Вносить изменения в проекты – запрещено 🙂 Read more…

Categories: MSBuild Tags: , , , , ,

Virtual directories creation order in InstallShield 2008

11.05.2010 Leave a comment

Недавно столкнулся со следующей проблемой – виртуальные папки при инсталляции создаются не в порядке иерархии, а по какому-то непонятному принципу. В результате этого возникала ошибка и установка прерывалась. Несколько часов (в инсталляторах я пока еще не спец) танцев с бубном и чтения лога дали результат. Как оказалось, каждой виртуальной папке, которую нужно создать, соответствует свой компонент (Component). Виртуальные папки во время установки создаются с помощью Custom Action’a caCreateVRoots, который в свою очередь вызывает функцию CreateIISVRoots из библиотеки IISHelper.dll. Так вот эта самая функция создает виртуальные дирректории не в порядке следования их в иерархии, а в алфавитном порядке соответствующих компонент (!!!). Путем добавления различных букв латинского алфавита к началам имен компонентов я добился того, чтобы папки создавались в правильном порядке.

Кстати, как ни удивительно, но Сеть по этому поводу молчит как партизан. Неужели никто при установке не создает вложенных виртуальных папок? Или это только я такой глупый, что не сразу догадался.

В любом случае, надеюсь, что кому-то моя статья сохранит несколько часов для более интересных занятий 😉

Script for Setting Item-level Security in Reporting Services

29.04.2010 Leave a comment

Название статьи практически цитирует название статьи Брайана Келлера (Bryan Keller), которую можно посмотреть тут: Sample Script for Setting Item-level Security in Reporting Services. Статья хорошая, скрипт очень полезный, если нужно раздать права на сервер репортинга при инсталляции, но есть одно НО. Он работает один раз. Точнее одному пользователю можно установить одну привилегию, не больше. В ситуации, когда пользователю нужно назначить например привилегии Browser и Browser for Microsoft CRM, то придется делать это двумя вызовами скрипта с разными параметрами и на втором вызове, к сожалению, скрипт выдаст ошибку. Возможно это связано с тем, что судя по дате публикации статьи Келлера, скрипт создавался под SQL Server 2000, а тестировал я на SQL Server 2008. В любом случае, предлагаю ознакомиться с небольшой модификацией функции Main(). В моем варианте, скрипт принимает в качестве параметра не имя привилегии, а набор привилегий, разделенных запятой.

Public Sub Main()
   Dim isRoot As Boolean = False
   Dim inheritParent As Boolean
   Dim policies() As Policy
   Dim newPolicies() As Policy
   Dim policy As New Policy()

   Dim roles_array As String()
        roles_array = SplitRoles(roleName)
        Dim i As Integer
        i = 0
        For Each s As String In roles_array
            i = i + 1
        Next

        Dim roles(i - 1) As Role
        i = 0

        For Each s As String In roles_array
            roles(i) = New Role()
            roles(i).Name = s
            i = i + 1
        Next

   policy.Roles = roles
   policy.GroupUserName = userName

   While Not isRoot
      ' Once the root of the catalog is reached,
      ' stop applying policies
      If itemPath = "/" Then
         isRoot = True
      End If
      policies = rs.GetPolicies(itemPath, inheritParent)

      ' If the user selects not to keep inherited or current policy,
      ' empty the policy
      If Not keepCurrentPolicy = "True" Then
         policies = Nothing
      End If
      newPolicies = AddNewPolicy(policy, policies)
      rs.SetPolicies(itemPath, newPolicies)
      itemPath = GetParentPath(itemPath)
   End While
   Console.WriteLine("Policy successfully set.")
End Sub 'Main

 Писался на скорую руку, а в VB.NET я не силен, поэтому дабы избежань недоразумений количество привилегий считал, как говорится на пальцах – проходом по массиву. Уж не взыщите)

Удачных инсталляций 😉

Точки расширения MSBuild’а

28.04.2010 Leave a comment

При создании автоматизированых билдов с помощью MSBuild очень важно точно понимать что за чем происходит и в какой момент можно вмешаться. Я например очень долго провозился, пытаясь заставить мои задачи копирования “увидеть” скомпилированные файлы из папки билда (DropLocation). В итоге оказалось, что копировать я пытаюсь после компиляции, но до выполнения цели DropBuild, поэтому файлов в целевой папке еще нет.

Итак, точки расширения в порядке выполнения целей MSBuild’ом: Read more…

Categories: MSBuild Tags: , ,

Отображение отчета из навигационной панели CRM 4.0

28.04.2010 6 comments

Иногда нужно поместить ссылку на отчет в навигационную панель для быстрого к нему доступа. Примером таких отчетов могут быть сводные отчеты производительности, dashboardы, административные отчеты. В любом случае, сделать это не сложно, если смириться с одной проблемой – нужно явно указывать идентификатор в ссылке. А это значит, что ссылку нужно менять при каждом развертывании (на тестовом сервере, на сервере разработки, на эксплуатационном сервере). Также нет уверенности, что идентификатор будет стабильным даже в рамках одного развертывания – отчет может быть удален (в результате сбоя например) и создан наново. Маловероятно, но все равно возможно. Было бы неплохо в ссылке задавать не идентификатор отчета, а что-то более постоянное, например его имя. Read more…