We are in the midst of building a custom portal for SCSM, contact us if you’d like to purchase it from us. Sales pitches aside Trying to get multiple pieces of information and sort it from SCSM isn’t easy. First of all you have to deal with the new Criteria garbage to query SCSM, as if LINQ or CAML wasn’t good enough, let’s create a brand new querying language that only product will use. Seriously Microsoft, get some unity already. I digress….

Getting incidents is pretty simple, however using that object isn’t. Rob Ford does a great job at trying to help understand it (http://scsmnz.net/c-code-snippets-for-service-manager-1/). That said, how do you “order by” or get more information like Status? It isn’t “easy peezie lemon squeezie” but you should be able to make sense of it. This took a few days to put together from a few different sources, so hopefully this will help somebody.

These code sample are in order, so copy each section and paste then your controller should work.

This should look familiar. We get our management packs and our user and build our first Criteria.

 var strSetting = ConfigurationManager.AppSettings["Group"];<br /> EnterpriseManagementGroup mg = new EnterpriseManagementGroup(strSetting);</p><p>//get our user<br /> var strUserName = GetIdentityUsername();<br /> //build criteria to get incidents where user is AffectedUser<br /> var strCriteria = String.Format(@"$Context/Path[Relationship='WorkItem!System.WorkItemAffectedUser' TypeConstraint='System!System.Domain.User']/Property[Type='System!System.Domain.User']/UserName$ Equal" + strUserName + @"");</p><p>//Get the management pack for Incident and projection<br /> ManagementPackClass mpcIncident = mg.EntityTypes.GetClass(new Guid("a604b942-4c7b-2fb2-28dc-61dc6f465c68"));<br /> ManagementPackTypeProjection mptpIncident = mg.EntityTypes.GetTypeProjection(new Guid("1862825e-21bc-3ab2-223e-2a7f2439ba75"));<br /> ManagementPack mpIncidentLibrary = mg.ManagementPacks.GetManagementPack(new Guid("DD26C521-7C2D-58C0-0980-DAC2DACB0900"));<br /> ObjectProjectionCriteria opcIncidents = new ObjectProjectionCriteria(strCriteria, mptpIncident, mpIncidentLibrary, mg);

The tricky part is order by. Well there is another new method call ObjectQueryOptions. It is some loose form of XML where you add some references to the management packs that you want to user to get data and how to setup the QueryOptions. the IObjectProjectionReader is the same but you add the new Query Options Object.

var strQuery = String.Format(@"&lt;Sorting xmlns=""http://Microsoft.EnterpriseManagement.Core.Sorting""&gt;<br /> &lt;Reference Id=""System.WorkItem.Incident.Library"" Version=""7.5.3079.0"" Alias=""WorkItem"" PublicKeyToken=""31bf3856ad364e35""/&gt;</p><p>&lt;Reference Id=""Microsoft.Windows.Library"" Version=""7.5.3079.0"" Alias=""WinLib"" PublicKeyToken=""31bf3856ad364e35""/&gt;<br /> &lt;SortProperty SortOrder=""Ascending""&gt;$Context/Property[Type='WorkItem!System.WorkItem.Incident']/Priority$&lt;/SortProperty&gt;<br /> &lt;SortProperty SortOrder=""Descending""&gt;$Context/Property[Type='WorkItem!System.WorkItem.Incident']/Id$&lt;/SortProperty&gt;<br /> &lt;/Sorting&gt;");<br /> ObjectQueryOptions orderedIncidents = new ObjectQueryOptions();<br /> orderedIncidents.AddSortProperty(strQuery, mptpIncident, mg);</p><p>IObjectProjectionReader&lt;EnterpriseManagementObject&gt; oprIncidents = mg.EntityObjects.GetObjectProjectionReader&lt;EnterpriseManagementObject&gt;(opcIncidents, orderedIncidents);

So now you have your data, but it’s all an object and you want to show the priority to the user. Well half of the fields in SCSM are relationships. So you have to setup a new Criteria and get a single workitem, for which you will need a foreach loop to get the status for each. Notice we are using a datatable which we will pass through to the View.

//create datatable to pass to view<br /> DataTable dt = new DataTable();<br /> DataRow dr = null;</p><p>dt.Columns.Add(new DataColumn("Incident", typeof(string)));<br /> dt.Columns.Add(new DataColumn("Status", typeof(string)));<br /> dt.Columns.Add(new DataColumn("Last Modified", typeof(string)));</p><p>foreach (EnterpriseManagementObjectProjection emopIncident in oprIncidents)<br /> {<br /> dr = dt.NewRow();<br /> dr["Incident"] = emopIncident.Object.DisplayName;</p><p>//This is the work item (such as a service request) ID that we're looking for<br /> String workItemId = emopIncident.Object.Name;</p><p>//Setup the criteria. This will instruct service manager to "Get me the incident request with Id: IR{0}"<br /> //Get the system.workitem class<br /> ManagementPackClass mpcWorkitem = mg.EntityTypes.GetClass(new Guid("f59821e2-0364-ed2c-19e3-752efbb1ece9"));</p><p>//Get system.workitem.library mp<br /> ManagementPack mpWorkitem = mg.ManagementPacks.GetManagementPack(new Guid("405d5590-b45f-1c97-024f-24338290453e"));</p><p>string strIncidentSearchCriteria = "";</p><p>//Attempt to get results for single workitem<br /> strIncidentSearchCriteria = String.Format(@"&lt;Criteria xmlns=""http://Microsoft.EnterpriseManagement.Core.Criteria/""&gt;" +<br /> "&lt;Expression&gt;" +<br /> "&lt;SimpleExpression&gt;" +<br /> "&lt;ValueExpressionLeft&gt;" +<br /> "&lt;Property&gt;$Context/Property[Type='System.WorkItem']/Id$&lt;/Property&gt;" +<br /> "&lt;/ValueExpressionLeft&gt;" +<br /> "&lt;Operator&gt;Equal&lt;/Operator&gt;" +<br /> "&lt;ValueExpressionRight&gt;" +<br /> "&lt;Value&gt;" + workItemId + "&lt;/Value&gt;" +<br /> "&lt;/ValueExpressionRight&gt;" +<br /> "&lt;/SimpleExpression&gt;" +<br /> "&lt;/Expression&gt;" +<br /> "&lt;/Criteria&gt;");</p><p>EnterpriseManagementObjectCriteria emocWorkitem = new EnterpriseManagementObjectCriteria((string)strIncidentSearchCriteria, mpcWorkitem, mpWorkitem, mg);<br /> IObjectReader&lt;EnterpriseManagementObject&gt; readerWorkitem = mg.EntityObjects.GetObjectReader&lt;EnterpriseManagementObject&gt;(emocWorkitem, ObjectQueryOptions.Default);<br /> EnterpriseManagementObject emoWorkItem = readerWorkitem.ElementAt(0);

Great I have my single workitem, now I need to get the status. Remember everything is a relationship. So you will have loop through the Status List until it matches and then output that. However if a status is empty it will throw an exception, so try catch to suppress errors. Then finish up the rest and add the row to the table.

String workItemStatus = "";</p><p>//you need a try catch for when the status is empty.<br /> try<br /> {<br /> //Get Status DisplayName for title<br /> Guid gStatusCategory = new Guid("5e2d3932-ca6d-1515-7310-6f58584df73e");</p><p>foreach (ManagementPackEnumeration mpeClass in mg.EntityTypes.GetChildEnumerations(gStatusCategory, TraversalDepth.Recursive))<br /> {<br /> if (mpeClass.Id.ToString() == emoWorkItem[mpcIncident, "Status"].Value.ToString()) ;<br /> {<br /> workItemStatus = mpeClass.DisplayName;<br /> break;<br /> }<br /> }<br /> }<br /> catch (Exception ex)<br /> {<br /> //workItemStatus = ex.Message + " | " + ex.Source;<br /> }</p><p>dr["Status"] = workItemStatus;<br /> dr["Last Modified"] = emopIncident.Object.LastModified.ToLocalTime();<br /> dt.Rows.Add(dr);<br /> }</p><p>return View(dt);