DIY Service Manager Analyst Portal – Part 3 – Viewing Details

The details.aspx and details.aspx.cs file is where we really get into the “fun” of working with the Service Manager SDK.  I should mention that we have extended the Incident class and forms to include extra fields that our organization needs (location, alternate schedule, room location, etc) that you will see in the code.  There is also a method to translate the Enumeration values (list of locations) stored by SCSM into friendly text.

HTML:


<%@ Page Language="C#" AutoEventWireup="true" CodeFile="details.aspx.cs" Inherits="test2" %>

<html>
<body>
<form id="form1" runat="server">
<div ID="lblActive" runat="server"></div>
<div id="activeDetails" runat="server"></div>

<div ID="lblPending" runat="server"></div>
<div id="pendingDetails" runat="server"></div>
</form>
</body>
</html>

C#:


using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.EnterpriseManagement;
using Microsoft.EnterpriseManagement.Common;
using Microsoft.EnterpriseManagement.Configuration;

.[Serializable()]
public class Incident : IComparable<Incident>
{
public String ID { get; set; }
public String Title { get; set; }
public String Description { get; set; }
public String AltContact { get; set; }
public String Location { get; set; }
public String Room { get; set; }
public String AltSchedule { get; set; }
public DateTime CreatedDate { get; set; }
public String AffectedUser { get; set; }
public String FileAttachment { get; set; }

public int CompareTo(Incident other)
{
return Location.CompareTo(other.Location);
}
}

public partial class test2 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
int cActive = 0;
int cPending = 0;

Session["tech"] = Request.QueryString["tech"];

String sUsername = Convert.ToString(Request.QueryString["tech"]);

String sActiveCriteria;
String sPendingCriteria;

if (sUsername == "unassigned")
{
sActiveCriteria = String.Format(@"<Criteria xmlns=""http://Microsoft.EnterpriseManagement.Core.Criteria/"">
<Expression>
<And>
<Expression>
<UnaryExpression>
<ValueExpression>
<Property>$Context/Path[Relationship='WorkItem!System.WorkItemAssignedToUser' TypeConstraint='System!System.Domain.User']/Property[Type='System!System.Domain.User']/LastName$</Property>
</ValueExpression>
<Operator>IsNull</Operator>
</UnaryExpression>
</Expression>
<Expression>
<SimpleExpression>
<ValueExpressionLeft>
<Property>$Context/Property[Type='CoreIncident!System.WorkItem.Incident']/Status$</Property>
</ValueExpressionLeft>
<Operator>Equal</Operator>
<ValueExpressionRight>
<Value>5e2d3932-ca6d-1515-7310-6f58584df73e</Value>
</ValueExpressionRight>
</SimpleExpression>
</Expression>
</And>
</Expression>
</Criteria>");

sPendingCriteria = String.Format(@"<Criteria xmlns=""http://Microsoft.EnterpriseManagement.Core.Criteria/"">
<Expression>
<And>
<Expression>
<UnaryExpression>
<ValueExpression>
<Property>$Context/Path[Relationship='WorkItem!System.WorkItemAssignedToUser' TypeConstraint='System!System.Domain.User']/Property[Type='System!System.Domain.User']/LastName$</Property>
</ValueExpression>
<Operator>IsNull</Operator>
</UnaryExpression>
</Expression>
<Expression>
<SimpleExpression>
<ValueExpressionLeft>
<Property>$Context/Property[Type='CoreIncident!System.WorkItem.Incident']/Status$</Property>
</ValueExpressionLeft>
<Operator>Equal</Operator>
<ValueExpressionRight>
<Value>b6679968-e84e-96fa-1fec-8cd4ab39c3de</Value>
</ValueExpressionRight>
</SimpleExpression>
</Expression>
</And>
</Expression>
</Criteria>");
}
else
{
sActiveCriteria = String.Format(@"<Criteria xmlns=""http://Microsoft.EnterpriseManagement.Core.Criteria/"">
<Expression>
<And>
<Expression>
<SimpleExpression>
<ValueExpressionLeft>
<Property>$Context/Path[Relationship='WorkItem!System.WorkItemAssignedToUser' TypeConstraint='System!System.Domain.User']/Property[Type='System!System.Domain.User']/LastName$</Property>
</ValueExpressionLeft>
<Operator>Equal</Operator>
<ValueExpressionRight>
<Value>{0}</Value>
</ValueExpressionRight>
</SimpleExpression>
</Expression>
<Expression>
<SimpleExpression>
<ValueExpressionLeft>
<Property>$Context/Property[Type='CoreIncident!System.WorkItem.Incident']/Status$</Property>
</ValueExpressionLeft>
<Operator>Equal</Operator>
<ValueExpressionRight>
<Value>5e2d3932-ca6d-1515-7310-6f58584df73e</Value>
</ValueExpressionRight>
</SimpleExpression>
</Expression>
</And>
</Expression>
</Criteria>", sUsername);

sPendingCriteria = String.Format(@"<Criteria xmlns=""http://Microsoft.EnterpriseManagement.Core.Criteria/"">
<Expression>
<And>
<Expression>
<SimpleExpression>
<ValueExpressionLeft>
<Property>$Context/Path[Relationship='WorkItem!System.WorkItemAssignedToUser' TypeConstraint='System!System.Domain.User']/Property[Type='System!System.Domain.User']/LastName$</Property>
</ValueExpressionLeft>
<Operator>Equal</Operator>
<ValueExpressionRight>
<Value>{0}</Value>
</ValueExpressionRight>
</SimpleExpression>
</Expression>
<Expression>
<SimpleExpression>
<ValueExpressionLeft>
<Property>$Context/Property[Type='CoreIncident!System.WorkItem.Incident']/Status$</Property>
</ValueExpressionLeft>
<Operator>Equal</Operator>
<ValueExpressionRight>
<Value>b6679968-e84e-96fa-1fec-8cd4ab39c3de</Value>
</ValueExpressionRight>
</SimpleExpression>
</Expression>
</And>
</Expression>
</Criteria>", sUsername);
}

EnterpriseManagementConnectionSettings settings = new EnterpriseManagementConnectionSettings("SCSM SERVER");
settings.UserName = "USER NAME";
char[] pass = { 'p', 'a', 's', 's', 'w', 'o', 'r', 'd'};
settings.Password = new System.Security.SecureString();
foreach (char c in pass)
settings.Password.AppendChar(c);
settings.Domain = "DOMAIN NAME";

EnterpriseManagementGroup emg = new EnterpriseManagementGroup(settings);

//Note - this projection isn't that great for performance but is provided in SCSM without the need to create your own
ManagementPackTypeProjection activemptp = emg.EntityTypes.GetTypeProjection(new Guid("285cb0a2-f276-bccb-563e-bb721df7cdec"));
ObjectProjectionCriteria activeopc = new ObjectProjectionCriteria(sActiveCriteria, activemptp, activemptp.GetManagementPack(), emg);
IObjectProjectionReader<EnterpriseManagementObject> activereader = emg.EntityObjects.GetObjectProjectionReader<EnterpriseManagementObject>(activeopc, ObjectQueryOptions.Default);
ManagementPackTypeProjection pendingmptp = emg.EntityTypes.GetTypeProjection(new Guid("285cb0a2-f276-bccb-563e-bb721df7cdec"));
ObjectProjectionCriteria pendingopc = new ObjectProjectionCriteria(sPendingCriteria, pendingmptp, pendingmptp.GetManagementPack(), emg);
IObjectProjectionReader<EnterpriseManagementObject> pendingreader = emg.EntityObjects.GetObjectProjectionReader<EnterpriseManagementObject>(pendingopc, ObjectQueryOptions.Default);

ManagementPackRelationship relIncidentAffectedUser = emg.EntityTypes.GetRelationshipClass(new Guid("DFF9BE66-38B0-B6D6-6144-A412A3EBD4CE"));

ManagementPackRelationship relIncidentFileAttachment = emg.EntityTypes.GetRelationshipClass(new Guid("aa8c26dc-3a12-5f88-d9c7-753e5a8a55b4"));

int n = 1;

cActive = activereader.Count();
cPending = pendingreader.Count();

List<Incident> incActiveArray = new List<Incident>();
List<Incident> incPendingArray = new List<Incident>();

String red = "#FF0000";
String green = "#00CC00";

foreach (EnterpriseManagementObjectProjection emop in activereader)
{
String date = emop.Object.Values[23].ToString();
DateTime created = Convert.ToDateTime(date);
created = created.ToLocalTime();

Incident newInc = new Incident();

newInc.ID = emop.Object.Name;
newInc.Title = emop.Object.Values[20].ToString();
newInc.Description = emop.Object.Values[21].ToString();
newInc.AltContact = emop.Object.Values[22].ToString();
newInc.Location = translate(emop.Object.Values[13].ToString());
newInc.Room = emop.Object.Values[11].ToString();
newInc.AltSchedule = emop.Object.Values[12].ToString();
newInc.CreatedDate = created;

if (emop[relIncidentAffectedUser.Target].Count > 0)
{
foreach (IComposableProjection icpAffectedUser in emop[relIncidentAffectedUser.Target])
{
String s = icpAffectedUser.Object.Name;
s = s.Replace(".", "\\");
newInc.AffectedUser = icpAffectedUser.Object.DisplayName + " (" + s + ")";
}
}
else
{
newInc.AffectedUser = "No user assigned";
}

if (emop[relIncidentFileAttachment.Target].Count > 0)
{
newInc.FileAttachment = "File attachment exists, please view in the SCSM console";
}
else
{
newInc.FileAttachment = "No file attachment";
}

incActiveArray.Add(newInc);
}

var sortResult = incActiveArray.OrderBy(a => a.Location).ThenBy(a => a.ID);

foreach (Incident inc in sortResult)
{
int days = (DateTime.Now.Date - inc.CreatedDate.Date).Days;

if (days < 7)
{
activeDetails.InnerHtml = activeDetails.InnerHtml + "<div style=\"color:" + green + "\"><h1>" + inc.ID + " (" + n + " of " + cActive + ")</h1></div>";
}
else
{
activeDetails.InnerHtml = activeDetails.InnerHtml + "<div style=\"color:" + red + "\"><h1>" + inc.ID + " (" + n + " of " + cActive + ")</h1></div>";
}

activeDetails.InnerHtml = activeDetails.InnerHtml + "<p><b>Title:</b> " + inc.Title + "</p>";
activeDetails.InnerHtml = activeDetails.InnerHtml + "<p><b>Description:</b> " + inc.Description + "</p>";
activeDetails.InnerHtml = activeDetails.InnerHtml + "<p><b>Alternate Contact Method:</b> " + inc.AltContact + "</p>";
activeDetails.InnerHtml = activeDetails.InnerHtml + "<p><b>Location:</b> " + inc.Location + "</p>";
activeDetails.InnerHtml = activeDetails.InnerHtml + "<p><b>Room:</b> " + inc.Room + "</p>";
activeDetails.InnerHtml = activeDetails.InnerHtml + "<p><b>Alt Schedule:</b> " + inc.AltSchedule + "</p>";
activeDetails.InnerHtml = activeDetails.InnerHtml + "<p><b>Created Date:</b> " + inc.CreatedDate + "</p>";
activeDetails.InnerHtml = activeDetails.InnerHtml + "<p><b>Affected User:</b> " + inc.AffectedUser + "</p>";
activeDetails.InnerHtml = activeDetails.InnerHtml + "<p><b>File Attachment:</b> " + inc.FileAttachment + "</p>";

activeDetails.InnerHtml = activeDetails.InnerHtml + "<p><a href=\"edit.aspx?ID=" + inc.ID + "\">Resolve Incident</a></p>";

activeDetails.InnerHtml = activeDetails.InnerHtml + "</div>";
activeDetails.InnerHtml = activeDetails.InnerHtml + "
";
activeDetails.InnerHtml = activeDetails.InnerHtml + "<hr />";
activeDetails.InnerHtml = activeDetails.InnerHtml + "
";

n++;
}

lblActive.InnerHtml = "<h1>Active Incidents: " + cActive + "</h1>";
lblActive.InnerHtml = lblActive.InnerHtml + "<hr />";
lblActive.InnerHtml = lblActive.InnerHtml + "<hr />";

n = 1;
foreach (EnterpriseManagementObjectProjection emop in pendingreader)
{
String date = emop.Object.Values[23].ToString();
DateTime created = Convert.ToDateTime(date);
created = created.ToLocalTime();

Incident newInc = new Incident();

newInc.ID = emop.Object.Name;
newInc.Title = emop.Object.Values[20].ToString();
newInc.Description = emop.Object.Values[21].ToString();
newInc.AltContact = emop.Object.Values[22].ToString();
newInc.Location = translate(emop.Object.Values[13].ToString());
newInc.Room = emop.Object.Values[11].ToString();
newInc.AltSchedule = emop.Object.Values[12].ToString();
newInc.CreatedDate = created;

if (emop[relIncidentAffectedUser.Target].Count > 0)
{
foreach (IComposableProjection icpAffectedUser in emop[relIncidentAffectedUser.Target])
{
String s = icpAffectedUser.Object.Name;
s = s.Replace(".", "\\");
newInc.AffectedUser = icpAffectedUser.Object.DisplayName + " (" + s + ")";
}
}
else
{
newInc.AffectedUser = "No user assigned";
}

if (emop[relIncidentFileAttachment.Target].Count > 0)
{
newInc.FileAttachment = "File attachment exists, please view in the SCSM console";
}
else
{
newInc.FileAttachment = "No file attachment";
}

incPendingArray.Add(newInc);
}

var sortPendingResult = incPendingArray.OrderBy(a => a.Location).ThenBy(a => a.ID);

foreach (Incident inc in sortPendingResult)
{
int days = (DateTime.Now.Date - inc.CreatedDate.Date).Days;

if (days < 7)
{
pendingDetails.InnerHtml = pendingDetails.InnerHtml + "<div style=\"color:" + green + "\"><h1>" + inc.ID + " (" + n + " of " + cPending + ")</h1></div>";
}
else
{
pendingDetails.InnerHtml = pendingDetails.InnerHtml + "<div style=\"color:" + red + "\"><h1>" + inc.ID + " (" + n + " of " + cPending + ")</h1></div>";
}

pendingDetails.InnerHtml = pendingDetails.InnerHtml + "<p><b>Title:</b> " + inc.Title + "</p>";
pendingDetails.InnerHtml = pendingDetails.InnerHtml + "<p><b>Description:</b> " + inc.Description + "</p>";
pendingDetails.InnerHtml = pendingDetails.InnerHtml + "<p><b>Alternate Contact Method:</b> " + inc.AltContact + "</p>";
pendingDetails.InnerHtml = pendingDetails.InnerHtml + "<p><b>Location:</b> " + inc.Location + "</p>";
pendingDetails.InnerHtml = pendingDetails.InnerHtml + "<p><b>Room:</b> " + inc.Room + "</p>";
pendingDetails.InnerHtml = pendingDetails.InnerHtml + "<p><b>Alt Schedule:</b> " + inc.AltSchedule + "</p>";
pendingDetails.InnerHtml = pendingDetails.InnerHtml + "<p><b>Created Date:</b> " + inc.CreatedDate + "</p>";
pendingDetails.InnerHtml = pendingDetails.InnerHtml + "<p><b>Affected User:</b> " + inc.AffectedUser + "</p>";
pendingDetails.InnerHtml = pendingDetails.InnerHtml + "<p><b>File Attachment:</b> " + inc.FileAttachment + "</p>";

pendingDetails.InnerHtml = pendingDetails.InnerHtml + "<p><a href=\"edit.aspx?ID=" + inc.ID + "\">Resolve Incident</a></p>";

pendingDetails.InnerHtml = pendingDetails.InnerHtml + "</div>";
pendingDetails.InnerHtml = pendingDetails.InnerHtml + "
";
pendingDetails.InnerHtml = pendingDetails.InnerHtml + "<hr />";
pendingDetails.InnerHtml = pendingDetails.InnerHtml + "
";

n++;
}

lblPending.InnerHtml = "<h1>Pending Incidents: " + cPending + "</h1>";
lblPending.InnerHtml = lblPending.InnerHtml + "<hr />";
lblPending.InnerHtml = lblPending.InnerHtml + "<hr />";

emg.Dispose();

}

public string translate(String strLocation)
{
switch (strLocation)
{
case "":
return "No location specified";
case "Enum.14cc8a0e69924da290753329d6568e41":
return "No location specified";
case "(null)":
return "No location specified";
case "Enum.0444226300e947f9bf173e72ff6dab16":
return "Location 1";
case "Enum.742fdc5e91194c08b48af5c7891af15d":
return "Location 2";
case "Enum.420e59a8160b4a9a9ae48a3039b9cfda":
return "Location 3";
}
return strLocation;
}
}

There is a lot going on in the code, but what it will give you is two lists of Incidents (in our case, sorted by location and created date so techs can see oldest to newest alphabetically by building location), first active incidents then pending.  Incidents older than a certain number of calendar days will be in red to indicate an aging call that needs to be dealt with and green for anything else.

The list will also tell if someone posted an attachment and if so direct them to the SCSM console to view it.  It may be possible to access it via the webpage but if that is true I haven’t figured it out yet.

Leave a comment