Creating (or Editing) an Object From a Template Programmatically

Creating (or Editing) an Object From a Template Programmatically

  • Comments 19
  • Likes

Sorry I haven’t been blogging in a while. I’ve been on a whirlwind tour around South Africa and Europe for the last three weeks presenting about Service Manager in one forum or another essentially every day.  It’s been exciting, but hasn’t left a lot of time for blogging.

I just needed to write some code today and had this question come up from our internal distribution list so I thought I would take a minute to answer it.  The question was how to create a new change request (or any object really) from a template programmatically.

Here you go:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.EnterpriseManagement;
using Microsoft.EnterpriseManagement.Common;
using Microsoft.EnterpriseManagement.Configuration;



namespace ApplyTemplate
{
    class Program
    {
        static void Main(string[] args)
        {
            EnterpriseManagementGroup emg = new EnterpriseManagementGroup("localhost");

            //You'll need to get the ObjectTemplateId GUID from the database after you have created it.  You can find it on the ObjectTemplate table by running a query like this:
            /*
             select MP.MPName,OT.* from ObjectTemplate as OT, ManagementPack as MP order by MP.MPName, OT.ObjectTemplateName 
             */
            ManagementPackObjectTemplate mpt = emg.Templates.GetObjectTemplate(new Guid("8B1AA102-F8A5-07D0-FC9A-2DB2A4FD5003"));  // <-- TODO: YOU'LL NEED TO REPLACE THIS GUID - SEE ABOVE

            //This is how you apply a template to a new object projection you want to create:
            EnterpriseManagementObjectProjection emop = new EnterpriseManagementObjectProjection(emg, mpt);
            emop.Overwrite();

            //This is how you apply a class-targeted template to an object.
            /*
            ManagementPackClass classChangeRequest = emg.EntityTypes.GetClass(new Guid("E6C9CF6E-D7FE-1B5D-216C-C3F5D2C7670C"));
            CreatableEnterpriseManagementObject cemo = new CreatableEnterpriseManagementObject(emg, classChangeRequest);
            cemo.ApplyTemplate(mpt);
            cemo.Commit();
            */
        }
    }
}

You can also call the .ApplyTemplate() method on a EnterpriseManaegmentObject or a EnterpriseManagementObjectProjection to update an object/projection that already exists.

The source code is attached in a Visual Studio application.

Attachment: ApplyTemplate.zip
Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • I've noticed that when I create a change request using this method and the Standard Change Request template, the new Change ID doesn't have the "CR" prefix. Does this need to be set manually when creating an Object programmatically?

  • @BrettHam -

    Yes, you need to retrieve the currently configured prefix and prepend it to the ID.

    If you're going to do this let me know and I'll provide you the exact code.  In pseudo code it would look like this:

    EnterpriseManagementObject emoCRIDPrefix = emg.GetObject(“some guid”);

    String strCRIDPrefix = emoCRIDPrefix[“IDPrefix”].Value;

    ….

    CreateableEnterpriseManagementObject cemo = new CreateableEnterpriseManagementObject();

    cemo[“ID”].Value = strCRIDPrefix + “{0}”;

    cemo.Submit();

  • Thanks Travis, that helped a lot, here's what I did:

    ManagementPackClass classCRSettings = emg.EntityTypes.GetClass(new Guid("c7fe33bb-9760-3f88-59fc-0951e3221be4"));

    EnterpriseManagementObject emoCRIDPrefix =

    emg.EntityObjects.GetObject<EnterpriseManagementObject>(new Guid("c7fe33bb-9760-3f88-59fc-0951e3221be4"), ObjectQueryOptions.Default);

    String strCRIDPrefix = emoCRIDPrefix[classCRSettings, "SystemWorkItemChangeRequestIdPrefix"].Value as String;

    emop.Object[classChangeRequest, "Id"].Value = strCRIDPrefix + "{0}";

  • @BrettHam

    Bingo!  Good work!

  • Hi Travis,

    When I try this using the same template that the Exchange Connector uses when an incident is created, I get:

    Only a template targeted at a class can be applied to a single object.

    This template is targetted at the incident class, so why does it fail?

    Cheers,

    Rob

  • @Rob - what is the Target attribute value for the template you are trying to use?

  • @Travis - I'm 100% sure if this is what you asked you, the template is targetted at "Incident" and the ObjectTemplateTypeId is 7BAC191B-6B22-C606-5F2D-09B753B0B0AE, the TypeId is "IncidentFormExtensions!CustomForm_9cc29543_6299_4152_9bb7_9f12f6691e87_TypeProjection" and I am trying to apply it to a CreatableEnterpriseManagementObject pointing at the Incident Class (A604B942-4C7B-2FB2-28DC-61DC6F465C68)

  • IncidentFormExtensions!CustomForm_9cc29543_6299_4152_9bb7_9f12f6691e87_TypeProjection is a type projection.  So, either you need to have a template which has a type ID = the incident class (I don't think you can do that from the UI) or you need to use a CreatableEnterpriseManagementProjectionObject class instead of CreatableEnterpriseManagementObject.

    As it stands right now you are applying a type projection template to an object instead of a type projection object.

  • @Travis - thanks, as a relative new-comer to Service Manager it is hard to understand these differences - I just see a template I've created in the console and it points at "Incident" so following your example above is all I have to go on :)

    I can't find CreatableEnterpriseManagementProjectionObject, what do I need to reference to see it?

  • @Rob - Sorry I forgot for some reason we dont have a CreatableEnterpriseManagementObjectProjection class.  You just need to do it like the example above:

               //This is how you apply a template to a new object projection you want to create:

               EnterpriseManagementObjectProjection emop = new EnterpriseManagementObjectProjection(emg, mpt);

               emop.Overwrite();

  • @Travis - thanks - I don't really understand how to apply that (to my cemo), I'll do some more research...

  • If you have a cemo and you want to apply a template to it you need to have a template which has a class as the TypeID instead of TypeProjection for the TypeID.

    Rather than use a cemo can you use an emop as above?

  • @Travis - thanks for bearing with me. I think the problem here is my luck of understanding in this particular area. I don't know how to create a new incident (or other class) using an emop instead of a cemo, if you have a blog example perhaps you could point me at it?

    I've gotten around it for now by hard-coding the required values into the code.

  • @Rob - No problem.  Hang in there.  Check out this blog post:

    blogs.technet.com/.../using-the-sdk-to-create-and-edit-objects-and-relationships-using-type-projections.aspx

    Especially example #5.

  • Hi Travis,

    I'm trying to apply a Change Request template that contains activities. I notice that the activities that get created after applying the template don't have the correct prefixes. Do I need to iterate through all the related items and make sure they have their prefixes set?

    Thanks!