Compartir a través de


del método Statusing.UpdateStatus

Aplica los cambios a asignaciones guardadas. El parámetro changexml es una diferencia de los cambios, con una opción para enviar asignaciones al jefe de proyecto.

Espacio de nombres:  WebSvcStatusing
Ensamblado:  ProjectServerServices (en ProjectServerServices.dll)

Sintaxis

'Declaración
<SoapDocumentMethodAttribute("https://schemas.microsoft.com/office/project/server/webservices/Statusing/UpdateStatus", RequestNamespace := "https://schemas.microsoft.com/office/project/server/webservices/Statusing/",  _
    ResponseNamespace := "https://schemas.microsoft.com/office/project/server/webservices/Statusing/",  _
    Use := SoapBindingUse.Literal, ParameterStyle := SoapParameterStyle.Wrapped)> _
Public Sub UpdateStatus ( _
    changexml As String _
)
'Uso
Dim instance As Statusing
Dim changexml As String

instance.UpdateStatus(changexml)
[SoapDocumentMethodAttribute("https://schemas.microsoft.com/office/project/server/webservices/Statusing/UpdateStatus", RequestNamespace = "https://schemas.microsoft.com/office/project/server/webservices/Statusing/", 
    ResponseNamespace = "https://schemas.microsoft.com/office/project/server/webservices/Statusing/", 
    Use = SoapBindingUse.Literal, ParameterStyle = SoapParameterStyle.Wrapped)]
public void UpdateStatus(
    string changexml
)

Parámetros

  • changexml
    Tipo: System.String

    Cadena XML que define los cambios.

Comentarios

La cadena XML que se pasan al método UpdateStatus debe cumplir con la estructura definida por el esquema de ChangeList.xsd.

An application user who has the StatusBrokerPermission global permission can use the UpdateStatus method to update assignment status without impersonation, by including the new ResID attribute of the Assn element in the changeXml parameter. For more information about the ChangeList schema, see Introduction to the ChangeList Schema and Statusing ChangeXML.

En Project Web App, al hacer clic en volver a calcular en la página Mis tareas, Project Server usa el método UpdateStatus .

Nota

Si usa UpdateStatus para cambiar el inicio o la fecha de finalización de una tarea, enviar la actualización al jefe de proyecto; Cuando el jefe de proyecto aprueba la actualización, el cambio se guarda en la base de datos de borrador. El elemento Web del centro de proyecto en Project Web App no mostrar el inicio o hasta que se publica el proyecto de fecha de finalización.

El atributo ResID del elemento Task en el esquema de la lista de cambios no funciona para los cambios de una tarea de otro usuario. El parámetro changeXml puede actualizar los campos de asignación, pero no los campos de tarea de otro usuario.

For more information about assignment and task fields that can be changed, see Supported Project Fields and Field Information for Statusing ChangeXML

Permisos de Project Server

Permiso

Descripción

LogOn

Permite al usuario iniciar sesión en el servidor. Permiso global.

Ejemplos

Ejemplo de WCF y las tareas programadas manualmente:   En el ejemplo UpdateStatus_ManualTasks es una aplicación de prueba que hace lo siguiente para una tarea programada manualmente o una tarea programada automáticamente:

  • Analiza el nombre del proyecto, el nombre de la tarea, el número de horas trabajadas, convierta en comentario el recurso optionalassigned y un estado opcional.

  • Si no se especifica ningún recurso, se supone que el usuario de la aplicación se asigna a la tarea.

  • Obtiene el GUID para el usuario asignado a la tarea especificada.

  • Obtiene y valida los datos de asignación. Se supone que se asigna un solo recurso.

  • Crea la cadena de changeXml para el método UpdateStatus . Para una prueba simple, convierte notificado horas en porcentaje completado (máximo 100). Si el usuario de la aplicación especifica un recurso diferente, agrega el atributo ResID al elemento Assn en la cadena de changeXml .

  • Llama a UpdateStatusy, a continuación, se llama SubmitStatusForResource, para la asignación única.

  • Llama a ReadStatusForResource para obtener una actualizado StatusingDataSet.

    La aplicación también escribe los conjuntos de datos y el valor de changeXml en archivos XML, para su uso en las pruebas.

Para usar la aplicación de prueba UpdateStatus , realice lo siguiente:

  1. Crear un proyecto de prueba, agregue dos tareas programadas manualmente, establecer duración de la tarea y fecha de inicio y, a continuación, agregue a usted y otro usuario como recursos. Asignar una tarea a usted y la otra tarea a otro usuario.

    Por ejemplo, asigne al proyecto el proyecto de prueba, el nombre de las tareas, T1 y T2 y, a continuación, establece la duración de cada tarea en tres días. Supongamos que su nombre de usuario es usuario 1 y el otro usuario es el usuario 2. Asignar T1 al usuario 1 y asignar T2 al usuario 2.

  2. For configuration of the WCF endpoints, create an app.config file. For information about using the code sample in a Microsoft Visual Studio 2010 project and creating an app.config file, see Prerequisites for WCF-Based Code Samples.

  3. Ejecute pruebas, con distintos parámetros. Vea el método Usage en el código siguiente para obtener información del parámetro. Por ejemplo, puede ejecutar las siguientes pruebas en una ventana del símbolo del sistema:

    • UpdateStatus -p "Test project" -t "T1" -hours 6 -c "This is a comment"

      Muestra el resultado:

      Updating status for User 1 on task 'T1': 6 hours
              Manually scheduled task
      
    • UpdateStatus -p "Test project" -t "T1" -hours 6 -r "User 2" -c "This is a comment"

      El usuario 2 no está asignado a la tarea T1, por lo que la aplicación de muestra The assignment on task 'T1' is for User 1, not for User 2.

    • UpdateStatus -p "Test project" -t "T2" -hours 6 -r "User 2" -c "This is a comment"

      Muestra el resultado:

      Updating status for User 2 on task 'T2': 6 hours
              Manually scheduled task
      
  4. Después de cada prueba, consulte el Centro de aprobación en Project Web App para actualizaciones de estado.

Nota

Cuando se agrega una tarea programada manualmente que no tiene una fecha de inicio o la duración, el valor predeterminado es ocho horas de trabajo. Todavía puede asignar un recurso a la tarea y actualizar el estado. Por ejemplo, si una tarea tiene T3 no iniciar fecha o la duración y usar la aplicación de prueba de UpdateStatus para establecer seis horas de trabajo para el recurso asignado, Project Server, se establece la fecha de inicio para T3 hasta la fecha de inicio del proyecto y, a continuación, agrega seis horas de trabajo real. Después de aceptar la actualización de estado, puede agregar las columnas de Trabajo real y el Trabajo restante a la vista Diagrama de Gantt en Project Professional 2010. El trabajo de T3 es de ocho horas, trabajo real es seis horas y el trabajo restante es de dos horas. Si agrega la fila Trabajo real en el panel de Detalles de la vista Uso de recursos o la vista Uso de tareas, también puede ver las seis horas de trabajo real.

La solución de Visual Studio completa está en la Project 2010 de descarga del SDK.

using System;
using System.Data;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Security.Principal;
using System.Xml;
using PSLibrary = Microsoft.Office.Project.Server.Library;

namespace Microsoft.SDK.Project.Samples.UpdateStatus
{
    class Program
    {
        private const string ENDPOINT_PROJECT = "basicHttp_Project";
        private const string ENDPOINT_RESOURCE = "basicHttp_Resource";
        private const string ENDPOINT_STATUSING = "basicHttp_Statusing";

        // Change the output directory for your computer.
        private const string OUTPUT_FILES = @"C:\Project\Samples\Output\";
        private const string XML_FILE1 = "UpdateStatus_jc_BasicProjectInfo.xml";
        private const string XML_FILE2 = "UpdateStatus_jc_FullProjectInfo.xml";
        private const string XML_FILE3 = "UpdateStatus_jc_ChangeXml.xml";
        private const string XML_FILE4 = "UpdateStatus_jc_NewStatus.xml";

        private static SvcProject.ProjectClient projectClient;
        private static SvcResource.ResourceClient resourceClient;
        private static SvcStatusing.StatusingClient statusingClient;

        private static string projectName = string.Empty;      // Project name.
        private static string taskName = string.Empty;         // Task name.
        private static string resName = string.Empty;          // Assigned resource name.
        private static string requestedResName = string.Empty; // Requested resource name.
        private static string appUserName = string.Empty;      // Application user name.
        private static DateTime minDate = DateTime.Today;      // Minimum date for statusing data.
        private static DateTime maxDate = DateTime.Today;      // Maximum date for statusing data.
        private static decimal hoursWorked = 0.0M;             // Number of hours worked on the assignment.
        private static string comment = string.Empty;          // Comment for status submission.

        private static bool showUsage = false;
        private static StreamWriter writer;
 
        static void Main(string[] args)
        {
            string outFilePath1 = OUTPUT_FILES + XML_FILE1;
            string outFilePath2 = OUTPUT_FILES + XML_FILE2;
            string outFilePath3 = OUTPUT_FILES + XML_FILE3;
            string outFilePath4 = OUTPUT_FILES + XML_FILE4;

            writer = new StreamWriter(outFilePath3);

            Guid projUid = Guid.Empty;          // GUID of the project.
            Guid taskUid = Guid.Empty;          // GUID of the task.
            Guid assnUid = Guid.Empty;          // GUID of the assignment.
            Guid resUid = Guid.Empty;           // GUID of the assigned resource.
            Guid requestedResUid = Guid.Empty;  // GUID of the requested resource, for submitting status.
            Guid myUid = Guid.Empty;            // GUID of the application user.
            double regularWork = 0;             // Assignment working time at the regular rate, 
                                                // in thousandths of minutes.
            bool isTaskManual = false;          // Specifies whether the task is manually scheduled.

            if (!ParseCommandLine(args)) 
            {
                Usage();
                ExitApp();
            }

            try
            {
                ConfigClientEndpoints(ENDPOINT_PROJECT);
                ConfigClientEndpoints(ENDPOINT_RESOURCE);
                ConfigClientEndpoints(ENDPOINT_STATUSING);

                WindowsIdentity winId = WindowsIdentity.GetCurrent();
                appUserName = winId.Name;

                myUid = resourceClient.GetCurrentUserUid();
                Console.WriteLine("User: {0}; PWA GUID: {1}", appUserName, myUid.ToString());

                // Get the basic information for the project.
                SvcProject.ProjectDataSet projectDs = projectClient.ReadProjectStatus(
                    Guid.Empty, SvcProject.DataStoreEnum.PublishedStore, projectName,
                    (int)PSLibrary.Project.ProjectType.Project);

                Console.WriteLine("XML output for ReadProjectStatus:\n\t{0}",
                    outFilePath1);
                projectDs.WriteXml(outFilePath1);

                projUid = projectDs.Project[0].PROJ_UID;

                if (projUid == Guid.Empty)
                    throw (new ArgumentException(
                        string.Format("\nThe project '{0}' does not exist.", projectName)));

                // Get the full information for the project.
                projectDs = projectClient.ReadProject(projUid,
                    SvcProject.DataStoreEnum.PublishedStore);
                Console.WriteLine("XML output for ReadProject:\n\t{0}", outFilePath2);
                projectDs.WriteXml(outFilePath2);

                bool isCurrentUser;  // Specifies whether the assignment is for the current user.

                // Get requested resource GUID. Exit if the requested resource is not a project resource.
                if (string.IsNullOrEmpty(requestedResName))
                {
                    // The current user is the requested resource.
                    isCurrentUser = true;

                    // Use a Linq query over the typed ProjectDataSet to check whether 
                    // the app user is a resource on the project.
                    var query = from r in projectDs.ProjectResource
                                where r.RES_UID == myUid
                                select new { r.RES_NAME };

                    foreach (var resRow in query)
                    {
                        requestedResName = resRow.RES_NAME;
                        requestedResUid = myUid;
                    }
                }
                else
                {
                    isCurrentUser = false;

                    var query = from r in projectDs.ProjectResource
                                where r.RES_NAME == requestedResName
                                select new { r.RES_UID };

                    foreach (var resRow in query)
                    {
                        requestedResUid = resRow.RES_UID;
                    }
                }

                if (requestedResUid == Guid.Empty)
                {
                    if (string.IsNullOrEmpty(requestedResName)) 
                        requestedResName = appUserName;

                    throw (new ArgumentException(
                        string.Format("\nThe resource '{0}' is not on the project '{1}'",
                                      requestedResName, projectName)));
                }

                // Get the assignment data for the task.
                for (int i = 0; i < projectDs.Assignment.Count; i++)
                {
                    if (projectDs.Assignment[i].TASK_NAME == taskName)
                    {
                        taskUid = projectDs.Assignment[i].TASK_UID;
                        assnUid = projectDs.Assignment[i].ASSN_UID;
                        resUid = projectDs.Assignment[i].RES_UID;
                        regularWork = projectDs.Assignment[i].ASSN_WORK;
                        minDate = projectDs.Assignment[i].ASSN_START_DATE;
                        maxDate = projectDs.Assignment[i].ASSN_FINISH_DATE;

                        // Get the assigned resource name.
                        for (int j = 0; j < projectDs.ProjectResource.Count; j++)
                        {
                            if (projectDs.ProjectResource[j].RES_UID == resUid)
                            {
                                resName = projectDs.ProjectResource[j].RES_NAME;
                                break;
                            }
                        }

                        // Is the task manually scheduled?
                        for (int t = 0; t < projectDs.Task.Count; t++)
                        {
                            if (projectDs.Task[t].TASK_UID == taskUid)
                            {
                                isTaskManual = projectDs.Task[t].TASK_IS_MANUAL;
                                break;
                            }
                        }
                        break;
                    }
                }
                ValidateAssignment(isCurrentUser, resUid, myUid, assnUid, requestedResUid);

                string changeXml = CreateChangeXml(projUid, assnUid, resUid, 
                                                   hoursWorked, regularWork, isCurrentUser);

                Console.WriteLine("XML output for ChangeXml:\n\t{0}", outFilePath3);
                writer.WriteLine(changeXml);

                Console.ForegroundColor = ConsoleColor.Yellow;
                string yellowString = "\nUpdating status for {0} on task '{1}': {2} hours\n\t";
                yellowString += (isTaskManual) ? "Manually scheduled task" : "Auto-scheduled task";
                Console.WriteLine(yellowString, resName, taskName, hoursWorked);
                Console.ResetColor();

                statusingClient.UpdateStatus(changeXml);

                Guid[] assignments = { assnUid };
                statusingClient.SubmitStatusForResource(resUid, assignments, comment); 

                SvcStatusing.StatusingDataSet statusingDs =
                    statusingClient.ReadStatusForResource(resUid, assnUid, minDate, maxDate);

                Console.WriteLine("\nXML output for ReadStatusForResource:\n\t{0}", outFilePath4);
                statusingDs.WriteXml(outFilePath4);
            }
            catch (FaultException fault)
            {
                // Use the WCF FaultException, because the ASMX SoapException does not 
                // exist in a WCF-based application.
                Console.ForegroundColor = ConsoleColor.Red;
                WriteFaultOutput(fault);
                Console.WriteLine();
                showUsage = true;
            }
            catch (Exception ex)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine(ex.Message);
                Console.WriteLine();
                showUsage = true;
            }
            finally
            {
                writer.Close();
                Console.ResetColor();
                if (showUsage) Usage();
                ExitApp();
            }
        }

        // Validate the assignment and the resource.
        private static void ValidateAssignment(bool isCurrentUser, Guid resUid, Guid myUid,
                                               Guid assnUid, Guid requestedResUid)
        {
            if (!isCurrentUser && resUid == myUid)
                throw (new ArgumentException(
                    string.Format("\nThe assignment on task '{0}' is for {1}, not for {2}",
                                  taskName, resName, requestedResName)));

            if (assnUid == Guid.Empty)
                throw (new ArgumentException(
                    string.Format("\nNo assignment for {0} on task '{0}'", resName, taskName)));

            if (requestedResUid != resUid)
                throw (new ArgumentException(
                    string.Format("\nResource '{0}' does not match assignment on task '{1}'",
                                  requestedResName, taskName)));
        }

        /// <summary>Create a ChangeXml string for the UpdateStatus method.</summary>
        /// <param name="projUid">Project GUID</param>
        /// <param name="assnUid">Assignment GUID</param>
        /// <param name="resUid">Resource GUID</param>
        /// <param name="hoursWorked">Number of hours worked.</param>
        /// <param name="totalRegHours">
        /// Total assigned hours at the regular rate, in thousandths of minutes.</param>
        /// <param name="isCurrentUser">True if the assignment is for the current user.</param>
        /// <returns></returns>
        private static string CreateChangeXml(Guid projUid, Guid assnUid, Guid resUid,  
            decimal hoursWorked, double totalRegHours, bool isCurrentUser)
        {
            StringBuilder cXmlBuilder = new StringBuilder("<Changes>");
            cXmlBuilder.AppendFormat("<Proj ID=\"{0}\">", projUid.ToString());
            cXmlBuilder.AppendFormat("<Assn ID=\"{0}\"", assnUid.ToString());

            // If the assignment is not for the current user, add the ResID attribute, 
            // and then close the Assn element.
            if (isCurrentUser)
                cXmlBuilder.Append(">");
            else
                cXmlBuilder.AppendFormat(" ResID=\"{0}\">", resUid.ToString());

            // Specify the process ID (PID) for percent work complete.
            // The "Supported Project Fields and Field Information for Statusing ChangeXML"  
            // SDK article shows the PID value is 251658274.
            string pidPctWorkComplete = PSLibrary.AssnConstID.s_apid_pct_wrk_complete.ToString(
                CultureInfo.InvariantCulture);

            // Calculate the percent work complete.
            int pctComplete = Convert.ToInt32(100 * hoursWorked / 
                              Convert.ToDecimal(totalRegHours / 1000 / 60));

            if (pctComplete > 100) pctComplete = 100;

            cXmlBuilder.AppendFormat("<Change PID=\"{0}\">{1}</Change>", pidPctWorkComplete,
                pctComplete.ToString());
            cXmlBuilder.Append("</Assn></Proj></Changes>");

            return cXmlBuilder.ToString();
        }

        // Extract a PSClientError object from the WCF FaultException object, and
        // then display the exception details and each error in the PSClientError stack.
        private static void WriteFaultOutput(FaultException fault)
        {
            string errAttributeName;
            string errAttribute;
            string errOut;
            string errMess = "".PadRight(30, '=') + "\r\n"
                + "Error details: " + "\r\n";

            PSLibrary.PSClientError error = Helpers.GetPSClientError(fault, out errOut);
            errMess += errOut;

            PSLibrary.PSErrorInfo[] errors = error.GetAllErrors();
            PSLibrary.PSErrorInfo thisError;

            for (int i = 0; i < errors.Length; i++)
            {
                thisError = errors[i];
                errMess += "\r\n".PadRight(30, '=') + "\r\nPSClientError output:\r\n";
                errMess += thisError.ErrId.ToString() + "\n";

                for (int j = 0; j < thisError.ErrorAttributes.Length; j++)
                {
                    errAttributeName = thisError.ErrorAttributeNames()[j];
                    errAttribute = thisError.ErrorAttributes[j];
                    errMess += "\r\n\t" + errAttributeName
                        + ": " + errAttribute;
                }
            }
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine(errMess);
            Console.ResetColor();
        }

        // Use the endpoints defined in app.config to configure the client.
        public static void ConfigClientEndpoints(string endpt)
        {
            if (endpt == ENDPOINT_PROJECT)
                projectClient = new SvcProject.ProjectClient(endpt);
            else if (endpt == ENDPOINT_RESOURCE)
                resourceClient = new SvcResource.ResourceClient(endpt);
            else if (endpt == ENDPOINT_STATUSING)
                statusingClient = new SvcStatusing.StatusingClient(endpt);
        }

        // Parse the command line. Return true if there are no errors.
        private static bool ParseCommandLine(string[] args)
        {
            int i;
            bool error = false;
            int argsLength = args.Length;

            for (i = 0; i < argsLength; i++)
            {
                if (error) break;
                if (args[i].StartsWith("-") || args[i].StartsWith("/"))
                    args[i] = "*" + args[i].Substring(1).ToLower();

                switch (args[i])
                {
                    case "*projectname":
                    case "*p":
                        if (++i >= argsLength) return false;
                        projectName = args[i];
                        break;
                    case "*taskname":
                    case "*t":
                        if (++i >= argsLength) return false;
                        taskName = args[i];
                        break;
                    case "*resourcename":
                    case "*r":
                        if (++i >= argsLength) return false;
                        requestedResName = args[i];
                        break;
                    case "*hours":
                    case "*h":
                        if (++i >= argsLength) return false;
                        hoursWorked = Convert.ToDecimal(args[i]);
                        break;
                    case "*comment":
                    case "*c":
                        if (++i >= argsLength) return false;
                        comment = args[i];
                        break;
                    case "*?":
                    default:
                        error = true;
                        break;
                }
            }
            return !error;
        }

        private static void Usage()
        {
            string example = "Usage: UpdateStatus -p \"Project Name\" -t \"Task name\"  -h 3"
                + "\r\n\t\t[-r \"Resource Name\"] [-d 6/29/2011] [-c \"This is a comment\"]";
            Console.WriteLine(example);
            Console.WriteLine("  -projectName | -p:  Name of the project.");
            Console.WriteLine("  -taskName | -t:  Name of the assigned task.");
            Console.WriteLine("  -hours | -h:  Number of hours worked.");
            Console.WriteLine("  -resourceName | -r:  Resource name. Default is the current user.");
            Console.WriteLine("  -date | -d:  Date of the work. Default is non-timephased.");
            Console.WriteLine("  -comment | -c:  Comment for submitted status.");
        }

        private static void ExitApp()
        {
            Console.Write("\nPress any key to exit... ");
            Console.ReadKey(true);
            Environment.Exit(0);
        }
    }

    // Helper method: GetPSClientError.
    class Helpers
    {
        /// <summary>
        /// Extract a PSClientError object from the ServiceModel.FaultException,
        /// for use in output of the GetPSClientError stack of errors.
        /// </summary>
        /// <param name="e"></param>
        /// <param name="errOut">Shows that FaultException has more information 
        /// about the errors than PSClientError has. FaultException can also contain 
        /// other types of errors, such as failure to connect to the server.</param>
        /// <returns>PSClientError object, for enumerating errors.</returns>
        public static PSLibrary.PSClientError GetPSClientError(FaultException e, 
                                                               out string errOut)
        {
            const string PREFIX = "GetPSClientError() returns null: ";
            errOut = string.Empty;
            PSLibrary.PSClientError psClientError = null;

            if (e == null)
            {
                errOut = PREFIX + "Null parameter (FaultException e) passed in.";
                psClientError = null;
            }
            else
            {
                // Get a ServiceModel.MessageFault object.
                var messageFault = e.CreateMessageFault();

                if (messageFault.HasDetail)
                {
                    using (var xmlReader = messageFault.GetReaderAtDetailContents())
                    {
                        var xml = new XmlDocument();
                        xml.Load(xmlReader);

                        var serverExecutionFault = xml["ServerExecutionFault"];
                        if (serverExecutionFault != null)
                        {
                            var exceptionDetails = serverExecutionFault["ExceptionDetails"];
                            if (exceptionDetails != null)
                            {
                                try
                                {
                                    errOut = exceptionDetails.InnerXml + "\r\n";
                                    psClientError = 
                                        new PSLibrary.PSClientError(exceptionDetails.InnerXml);
                                }
                                catch (InvalidOperationException ex)
                                {
                                    errOut = PREFIX + "Unable to convert fault exception info ";
                                    errOut += "a valid Project Server error message. Message: \n\t";
                                    errOut += ex.Message;
                                    psClientError = null;
                                }
                            }
                            else
                            {
                                errOut = PREFIX 
                                    + "The FaultException e is a ServerExecutionFault, "
                                    + "but does not have ExceptionDetails.";
                            }
                        }
                        else
                        {
                            errOut = PREFIX 
                                + "The FaultException e is not a ServerExecutionFault.";
                        }
                    }
                }
                else // No detail in the MessageFault.
                {
                    errOut = PREFIX + "The FaultException e does not have any detail.";
                }
            }
            errOut += "\r\n" + e.ToString() + "\r\n";
            return psClientError;
        }
    }
}

Ejemplo de ASMX:  En el ejemplo de código siguiente se crea un proyecto de ejemplo con el usuario actual como un recurso disponible asignado a una tarea. A continuación, se actualiza la asignación y se envía la actualización para su aprobación mediante el Administrador de estado.

For critical information about running this code example, see Prerequisites for ASMX-Based Code Samples.

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Data;
using System.Web.Services.Protocols;
using System.Threading;
using PSLibrary = Microsoft.Office.Project.Server.Library;

namespace Microsoft.SDK.Project.Samples.UpdateStatus
{
   class Program
   {
      [STAThread]
      static void Main()
      {
         try
         {
            #region Setup
            const string PROJECT_SERVER_URI = "https://ServerName/ProjectServerName/"; // <<--Change to match your project server and directory
            const string STATUSING_SERVICE_PATH = "_vti_bin/psi/statusing.asmx";
            const string PROJECT_SERVICE_PATH = "_vti_bin/psi/project.asmx";
            const string RESOURCE_SERVICE_PATH = "_vti_bin/psi/resource.asmx";
            const string QUEUESYSTEM_SERVICE_PATH = "_vti_bin/psi/queuesystem.asmx";

            SvcStatusing.StatusingDataSet statusingDs;

            // Set up the services.
            SvcStatusing.Statusing statusingSvc = new SvcStatusing.Statusing();
            statusingSvc.UseDefaultCredentials = true;
            statusingSvc.Url = PROJECT_SERVER_URI + STATUSING_SERVICE_PATH;

            SvcProject.Project projectSvc = new SvcProject.Project();
            projectSvc.Url = PROJECT_SERVER_URI + PROJECT_SERVICE_PATH;
            projectSvc.UseDefaultCredentials = true;

            SvcResource.Resource resourceSvc = new SvcResource.Resource();
            resourceSvc.Url = PROJECT_SERVER_URI + RESOURCE_SERVICE_PATH;
            resourceSvc.UseDefaultCredentials = true;

            SvcQueueSystem.QueueSystem q = new SvcQueueSystem.QueueSystem();
            q.Url = PROJECT_SERVER_URI + QUEUESYSTEM_SERVICE_PATH;
            q.UseDefaultCredentials = true;
          
            Guid myUid = resourceSvc.GetCurrentUserUid();

            //Create sample project.
            Console.WriteLine("Creating the project");
            Guid projectUid = CodeSampleUtilities.CreateSampleProject(projectSvc, q, resourceSvc);

            // Read project back in.
            SvcProject.ProjectDataSet projectDs = projectSvc.ReadProject(projectUid, SvcProject.DataStoreEnum.PublishedStore);
            Guid assn = Guid.Empty;
            // Get assignment for current user.
            for(int i=0;i<projectDs.Assignment.Count;i++)
            {
               if(projectDs.Assignment[i].RES_UID==myUid)
               {
                  assn=projectDs.Assignment[i].ASSN_UID;
                  break;
               }
            }

            if(assn==Guid.Empty)
            {
               throw(new ApplicationException("No assignments were found for the current user"));
            }


            //Display on console so we can see references.
            Console.ForegroundColor = ConsoleColor.DarkYellow;
            Console.WriteLine("".PadRight(Console.BufferWidth, '='));
            Console.ResetColor();

            Console.WriteLine("Before: ");
            CodeSampleUtilities.WriteTablesToConsole(projectDs.Tables);
            Console.ForegroundColor = ConsoleColor.DarkYellow;
            Console.WriteLine("".PadRight(Console.BufferWidth, '='));
            Console.ResetColor();
            #endregion
            #region Create updates to assignments
            //Create ChangeXML.
            StringBuilder changeXml = new StringBuilder();
            changeXml.AppendFormat("<Changes><Proj ID=\"{0}\">", projectUid.ToString());
            changeXml.AppendFormat("<Assn ID=\"{0}\">", assn.ToString());
            string pidPctWorkComplete = PSLibrary.AssnConstID.s_apid_pct_wrk_complete.ToString(System.Globalization.CultureInfo.InvariantCulture);
            string pidOvertimeWork = PSLibrary.AssnConstID.s_apid_ovt_work.ToString(System.Globalization.CultureInfo.InvariantCulture);
            changeXml.AppendFormat("<Change PID=\"{0}\">{1}</Change>", pidPctWorkComplete, "50");
            changeXml.AppendFormat("<Change PID=\"{0}\">{1}</Change>", pidOvertimeWork, 60*10000*8);// 8 hours
            changeXml.Append("</Assn></Proj></Changes>");
            Console.WriteLine("Updating Status");
            #endregion 
            #region Update Status
            statusingSvc.UpdateStatus(changeXml.ToString());
            #endregion
            #region Display Results
            // Read the new assignment status.
            statusingDs = statusingSvc.ReadStatus(assn, DateTime.MinValue, DateTime.MaxValue);
            Console.ForegroundColor = ConsoleColor.DarkYellow;
            Console.WriteLine("".PadRight(Console.BufferWidth, '='));
            Console.ResetColor();

            CodeSampleUtilities.WriteTablesToConsole(statusingDs.Tables);

            Console.ForegroundColor = ConsoleColor.DarkYellow;
            Console.WriteLine("".PadRight(Console.BufferWidth, '='));
            Console.ResetColor();
            #endregion
            #region Submit assignment updates
            statusingSvc.SubmitStatus(new Guid[] { assn }, "Updated work and overtime");

            Console.WriteLine("Updates to assignments are processed and submitted for approval.");
            #endregion
         }
         catch (SoapException ex)
         {
            ExceptionHandlers.HandleSoapException(ex);
         }
         catch (WebException ex)
         {
            ExceptionHandlers.HandleWebException(ex);
         }
         catch (Exception ex)
         {
            ExceptionHandlers.HandleException(ex);
         }
         finally
         {
            ExceptionHandlers.ResetConsole();
         }
      }
   }

   class ExceptionHandlers
   {

      public static void HandleSoapException(SoapException ex)
      {
         PSLibrary.PSClientError error = new PSLibrary.PSClientError(ex);
         PSLibrary.PSErrorInfo[] errors = error.GetAllErrors();
         string errMess = "==============================\r\nError: \r\n";
         for (int i = 0; i < errors.Length; i++)
         {
            errMess += "\n" + ex.Message.ToString() + "\r\n";
            errMess += "".PadRight(30, '=') + "\r\nPSCLientError Output:\r\n \r\n";
            errMess += errors[i].ErrId.ToString() + "\n";

            for (int j = 0; j < errors[i].ErrorAttributes.Length; j++)
            {
               errMess += "\r\n\t" + errors[i].ErrorAttributeNames()[j] + ": "
                  + errors[i].ErrorAttributes[j];
            }
            errMess += "\r\n".PadRight(30, '=');
         }
         Console.ForegroundColor = ConsoleColor.Red;
         Console.WriteLine(errMess);
      }

      public static void HandleWebException(WebException ex)
      {
         string errMess = ex.Message.ToString() +
            "\n\nLog on, or check the Project Server Queuing Service";
         Console.ForegroundColor = ConsoleColor.Red;
         Console.WriteLine("Error: " + errMess);
      }

      public static void HandleException(Exception ex)
      {
         Console.ForegroundColor = ConsoleColor.Red;
         Console.WriteLine("Error: " + ex.Message);
      }

      public static void ResetConsole()
      {
         Console.ResetColor();
         Console.WriteLine("\r\n\r\nPress any key...");
         Console.ReadKey();
      }
   }
   class CodeSampleUtilities
   {
      // Write all contents of a table collection to the console.
      public static void WriteTablesToConsole(System.Data.DataTableCollection theTables)
      {
         Console.ForegroundColor = ConsoleColor.DarkGreen;
         foreach (System.Data.DataTable table in theTables)
         {

            int[] columnWidths = new int[table.Columns.Count];
            int tableWidth = 0;
            string dataString;
            Console.WriteLine("Table: " + table.TableName);

            // Write out the column names and get their spacing.
            StringBuilder tableRow = new StringBuilder();
            for (int i = 0; i < table.Columns.Count; i++)
            {
               columnWidths[i] = GetColumnWidth(table.Columns[i]);
               tableRow.Append(table.Columns[i].ColumnName.PadRight(columnWidths[i]));

               tableWidth += columnWidths[i];
            }
            // Add a space so it will not wrap.
            tableWidth += 1;
            // Make the console as wide as the widest table.
            Console.BufferWidth = (Console.BufferWidth > tableWidth ? Console.BufferWidth : tableWidth);
            tableRow.Append("\r\n");
            Console.Write(tableRow.ToString());

            // Write out the data.
            foreach (DataRow row in table.Rows)
            {
               tableRow = new StringBuilder();
               for (int i = 0; i < table.Columns.Count; i++)
               {

                  dataString = row[i].ToString();
                  // Truncate output if it is wider than 
                  // the desired column width.
                  if (dataString.Length >= columnWidths[i])
                  {
                     dataString = dataString.Substring(0, columnWidths[i] - 1);
                  }
                  // Add the output to the stringbuilder and pad right to fill
                  // up to the column width.
                  tableRow.Append(dataString.PadRight(columnWidths[i]));
               }
               tableRow.Append("\r\n");
               Console.Write(tableRow.ToString());
            }
            Console.Write("\r\n".PadLeft(tableWidth, '-'));
         }
         Console.ResetColor();
      }
      // Helper function for WriteTablesToConsole.
      private static int GetColumnWidth(DataColumn column)
      {
         // Note: Might not handle byte[]data types well.
         const int MAX_COL_WIDTH = 40;
         int dataWidth = 0;

         //Return 12 for numbers, 30 for dates, and string width for strings.
         switch (column.DataType.UnderlyingSystemType.ToString())
         {
            case "System.Boolean":
            case "System.Byte":
            case "System.Byte[]":
            case "System.Char":
            case "System.Decimal":
            case "System.Double":
            case "System.Int16":
            case "System.Int32":
            case "System.Int64":
            case "System.SByte":
            case "System.Single":
            case "System.UInt16":
            case "System.UInt32":
            case "System.UInt64":
               dataWidth = 12;
               break;
            case "System.DateTime":
            case "System.TimeSpan":
               dataWidth = 30;
               break;
            case "System.Guid":
               dataWidth = 37;
               break;
            case "System.String":
               // If it has a maxlength, use it.
               if (column.MaxLength > 0)
               {
                  dataWidth = column.MaxLength;
               }
               else
               {
                  // Otherwise, use the max col width.
                  dataWidth = MAX_COL_WIDTH;
               }
               break;
            default:
               dataWidth = column.ColumnName.Length;
               break;
         }
         // Truncate if over the maxlength.
         if (dataWidth > MAX_COL_WIDTH)
         {
            dataWidth = MAX_COL_WIDTH;
         }
         // Always be at least as wide as the colum name.
         return (column.ColumnName.Length > (dataWidth) ? column.ColumnName.Length + 1 : dataWidth);
      }
      // Wait for the job to finish.
      // Outputs job status to the console.
      static public void WaitForQueue(SvcQueueSystem.QueueSystem q, Guid jobId)
      {
         SvcQueueSystem.JobState jobState;
         const int QUEUE_WAIT_TIME = 1; // one second
         bool jobDone = false;
         string xmlError = string.Empty;
         int wait = 0;

         //Wait for the project to get through the queue.
         // - Get the estimated wait time in seconds.
         wait = q.GetJobWaitTime(jobId);

         // - Wait for it.
         Console.Write("Waiting on queue. Estimate: {0} seconds.\r\n ", wait);

         // - Wait until it is done.

         do
         {
            // - Get the job state.
            jobState = q.GetJobCompletionState(jobId, out xmlError);

            if (jobState == SvcQueueSystem.JobState.Success)
            {
               jobDone = true;
            }
            else
            {
               if (jobState == SvcQueueSystem.JobState.Unknown
               || jobState == SvcQueueSystem.JobState.Failed
               || jobState == SvcQueueSystem.JobState.FailedNotBlocking
               || jobState == SvcQueueSystem.JobState.CorrelationBlocked
               || jobState == SvcQueueSystem.JobState.Canceled)
               {
                  // If the job failed, error out.
                  throw (new ApplicationException("Queue request " + jobState + " for Job ID " + jobId + ".\r\n" + xmlError));
               }
               else
               {
                  //Console.WriteLine("Job State: " + jobState + " for Job ID: " + jobId);
                  Console.Write("~");
                  Thread.Sleep(QUEUE_WAIT_TIME * 1000);
               }
            }
         }
         while (!jobDone);
         Console.Write("\r\n");

      }

      static public Guid CreateSampleProject(SvcProject.Project projectSvc, SvcQueueSystem.QueueSystem q, SvcResource.Resource resourceSvc)
      {
         SvcProject.ProjectDataSet projectDs = new SvcProject.ProjectDataSet();
         Guid jobId;
         Guid sessionUid = Guid.NewGuid();
         const string SESSION_DESC = "Test Utility";

         // Create the project.
         SvcProject.ProjectDataSet.ProjectRow projectRow = projectDs.Project.NewProjectRow();
         Guid projectId = Guid.NewGuid();
         projectRow.PROJ_UID = projectId;
         projectRow.PROJ_NAME = "Its a wonderful project at " + DateTime.Now.ToShortDateString().Replace("/", "") + " " + DateTime.Now.ToShortTimeString().Replace(":", "") + " " + DateTime.Now.Millisecond.ToString();
         projectRow.PROJ_TYPE = (int)PSLibrary.Project.ProjectType.Project;
         projectDs.Project.AddProjectRow(projectRow);

         // Add some tasks.
         SvcProject.ProjectDataSet.TaskRow taskOne = projectDs.Task.NewTaskRow();
         taskOne.PROJ_UID = projectId;
         taskOne.TASK_UID = Guid.NewGuid();
         taskOne.TASK_NAME = "Task One";
         taskOne.TASK_DUR_FMT = (int)PSLibrary.Task.DurationFormat.Hour;
         taskOne.TASK_DUR = 10 * 60 * 8 * 3;//Three eight hour days
         taskOne.TASK_START_DATE = System.DateTime.Now.AddDays(1);
         projectDs.Task.AddTaskRow(taskOne);

         SvcProject.ProjectDataSet.TaskRow taskTwo = projectDs.Task.NewTaskRow();
         taskTwo.PROJ_UID = projectId;
         taskTwo.TASK_UID = Guid.NewGuid();
         taskTwo.TASK_NAME = "Task Two";
         taskTwo.TASK_DUR = 10 * 60 * 6;// 6 hours
         taskTwo.TASK_DUR_FMT = (int)PSLibrary.Task.DurationFormat.EHour; // Duration Estimate and shoudl be displayed in hours
         projectDs.Task.AddTaskRow(taskTwo);

         // Make second task dependent on first task. 
         SvcProject.ProjectDataSet.DependencyRow dependency = projectDs.Dependency.NewDependencyRow();
         dependency.LINK_UID = Guid.NewGuid();
         dependency.PROJ_UID = projectId;
         dependency.LINK_PRED_UID = taskOne.TASK_UID;
         dependency.LINK_SUCC_UID = taskTwo.TASK_UID;
         dependency.LINK_TYPE = 1;//Finish to Start
         dependency.LINK_LAG_FMT = (int)PSLibrary.Task.DurationFormat.Hour;
         dependency.LINK_LAG = 0;
         projectDs.Dependency.AddDependencyRow(dependency);

         // Add a summary task.
         SvcProject.ProjectDataSet.TaskRow taskOthers = projectDs.Task.NewTaskRow();
         taskOthers.PROJ_UID = projectId;
         taskOthers.TASK_UID = Guid.NewGuid();
         taskOthers.TASK_NAME = "Related Tasks";
         projectDs.Task.AddTaskRow(taskOthers);

         // Add some subtasks.
         SvcProject.ProjectDataSet.TaskRow taskThree = projectDs.Task.NewTaskRow();
         taskThree.PROJ_UID = projectId;
         taskThree.TASK_UID = Guid.NewGuid();
         taskThree.TASK_NAME = "Task Three";
         taskThree.TASK_PARENT_UID = taskOthers.TASK_UID;
         taskThree.TASK_OUTLINE_LEVEL = 2;
         taskThree.TASK_DUR = 9600; //Two days
         taskThree.TASK_DUR_FMT = (int)PSLibrary.Task.DurationFormat.Day;
         projectDs.Task.AddTaskRow(taskThree);

         SvcProject.ProjectDataSet.TaskRow taskFour = projectDs.Task.NewTaskRow();
         taskFour.PROJ_UID = projectId;
         taskFour.TASK_UID = Guid.NewGuid();
         taskFour.TASK_NAME = "Task Four";
         taskFour.TASK_PARENT_UID = taskOthers.TASK_UID;
         taskFour.TASK_DUR = 4800; //One day
         taskFour.TASK_DUR_FMT = (int)PSLibrary.Task.DurationFormat.Hour;
         taskFour.TASK_OUTLINE_LEVEL = 2;
         projectDs.Task.AddTaskRow(taskFour);


         // Make fourth task dependent on third task. 
         dependency = projectDs.Dependency.NewDependencyRow();
         dependency.LINK_UID = Guid.NewGuid();
         dependency.PROJ_UID = projectId;
         dependency.LINK_PRED_UID = taskThree.TASK_UID;
         dependency.LINK_SUCC_UID = taskFour.TASK_UID;
         dependency.LINK_TYPE = 1;//Finish to Start
         dependency.LINK_LAG = 0;
         projectDs.Dependency.AddDependencyRow(dependency);

         // Make other tasks dependent on second task. 
         dependency = projectDs.Dependency.NewDependencyRow();
         dependency.LINK_UID = Guid.NewGuid();
         dependency.PROJ_UID = projectId;
         dependency.LINK_PRED_UID = taskTwo.TASK_UID;
         dependency.LINK_SUCC_UID = taskOthers.TASK_UID;
         dependency.LINK_TYPE = 1;//Finish to Start
         dependency.LINK_LAG = 0;
         projectDs.Dependency.AddDependencyRow(dependency);

         //Add some local project resources.
         SvcProject.ProjectDataSet.ProjectResourceRow resourceOne = projectDs.ProjectResource.NewProjectResourceRow();
         resourceOne.PROJ_UID = projectId;
         resourceOne.RES_UID = Guid.NewGuid();
         resourceOne.RES_NAME = "Brynja Sigrídur Blomsterberg";
         resourceOne.RES_INITIALS = "BSB";
         projectDs.ProjectResource.AddProjectResourceRow(resourceOne);
         CreateAssignment(projectDs, taskOne.TASK_UID, resourceOne.RES_UID);
         CreateAssignment(projectDs, taskTwo.TASK_UID, resourceOne.RES_UID);

         SvcProject.ProjectDataSet.ProjectResourceRow resourceTwo = projectDs.ProjectResource.NewProjectResourceRow();
         resourceTwo.PROJ_UID = projectId;
         resourceTwo.RES_UID = Guid.NewGuid();
         resourceTwo.RES_NAME = "Ioannis Xylaras";
         resourceTwo.RES_INITIALS = "IX";
         projectDs.ProjectResource.AddProjectResourceRow(resourceTwo);
         CreateAssignment(projectDs, taskOne.TASK_UID, resourceTwo.RES_UID);
         CreateAssignment(projectDs, taskTwo.TASK_UID, resourceTwo.RES_UID);
         CreateAssignment(projectDs, taskThree.TASK_UID, resourceTwo.RES_UID);
         CreateAssignment(projectDs, taskFour.TASK_UID, resourceTwo.RES_UID);

         // Save the project to the database.
         jobId = Guid.NewGuid();
         projectSvc.QueueCreateProject(jobId, projectDs, false);
         CodeSampleUtilities.WaitForQueue(q, jobId);

         // Add or retrieve an enterprise resource.
         SvcResource.ResourceDataSet resourceDs = EnsureEnterpriseResource(resourceSvc);

         // Add the resource to the team.
         SvcProject.ProjectTeamDataSet projectTeamDs = new SvcProject.ProjectTeamDataSet();
         ProjectTeamAddResource(projectTeamDs, projectId, resourceDs.Resources[0].RES_UID, resourceDs.Resources[0].RES_UID);

         // Add the current user to the team.
         Guid myUid = resourceSvc.GetCurrentUserUid();
         ProjectTeamAddResource(projectTeamDs, projectId, myUid, myUid);
         projectSvc.CheckOutProject(projectId, sessionUid, SESSION_DESC);

         // Save the team!
         jobId = Guid.NewGuid();
         projectSvc.QueueUpdateProjectTeam(jobId, sessionUid, projectId, projectTeamDs);
         CodeSampleUtilities.WaitForQueue(q, jobId);

         // Read the project back in to get the updated team.
         projectDs = projectSvc.ReadProject(projectId, SvcProject.DataStoreEnum.WorkingStore);

         // Add the resource to an assignment
         CreateAssignment(projectDs, taskOne.TASK_UID, resourceDs.Resources[0].RES_UID, projectId);
        
         // Add the current user to an assignment.
         CreateAssignment(projectDs, taskThree.TASK_UID, myUid, projectId);

         // Save enterprise assignment.
         jobId = Guid.NewGuid();
         // Get only the added rows
         projectDs = (SvcProject.ProjectDataSet)projectDs.GetChanges(DataRowState.Added);
         projectSvc.QueueAddToProject(jobId, sessionUid, projectDs, false);
         CodeSampleUtilities.WaitForQueue(q, jobId);

         // Check in the project.
         jobId = Guid.NewGuid();
         projectSvc.QueueCheckInProject(jobId, projectId, false, sessionUid, SESSION_DESC);
         CodeSampleUtilities.WaitForQueue(q, jobId);

         // Publish the project.
         jobId = Guid.NewGuid();
         projectSvc.QueuePublish(jobId, projectId, false, String.Empty);
         CodeSampleUtilities.WaitForQueue(q, jobId);

         return projectRow.PROJ_UID;
      }
      // Helper function for CreateSampleProject.
      // Makes a simple assignment.
      private static void CreateAssignment(SvcProject.ProjectDataSet projectDs, Guid taskGuid, Guid resourceGuid)
      {
         CreateAssignment(projectDs, taskGuid, resourceGuid, projectDs.Project[0].PROJ_UID);
      }
      private static void CreateAssignment(SvcProject.ProjectDataSet projectDs, Guid taskGuid, Guid resourceGuid, Guid projectId)
      {
         SvcProject.ProjectDataSet.AssignmentRow assnRow = projectDs.Assignment.NewAssignmentRow();
         assnRow.PROJ_UID = projectId;
         assnRow.ASSN_UID = Guid.NewGuid();
         assnRow.TASK_UID = taskGuid;
         assnRow.RES_UID = resourceGuid;
         projectDs.Assignment.AddAssignmentRow(assnRow);
      }
      // Helper function for CreateProject.
      // Adds an enterprise resource to the project
      // so it can be used on the project.
      public static void ProjectTeamAddResource(SvcProject.ProjectTeamDataSet projTeamDataSet, Guid projGuid, Guid resGuid, Guid newResGuid)
      {
         SvcProject.ProjectTeamDataSet.ProjectTeamRow projTeamRow = projTeamDataSet.ProjectTeam.NewProjectTeamRow();
         projTeamRow.PROJ_UID = projGuid;
         projTeamRow.RES_UID = resGuid;
         projTeamRow.NEW_RES_UID = newResGuid;
         projTeamDataSet.ProjectTeam.AddProjectTeamRow(projTeamRow);
      }
      // Helper function for CreateProject.
      // Creates or retrieves an enterprise resource
      private static SvcResource.ResourceDataSet EnsureEnterpriseResource(SvcResource.Resource resourceSvc)
      {
         const string RES_NAME = "Lertchai Treetawatchaiwong";
         SvcResource.ResourceDataSet resourceDs = new SvcResource.ResourceDataSet();

         PSLibrary.Filter resourceFilter = new Microsoft.Office.Project.Server.Library.Filter();
         resourceFilter.FilterTableName = resourceDs.Resources.TableName;
         resourceFilter.Fields.Add(new PSLibrary.Filter.Field(resourceDs.Resources.TableName, resourceDs.Resources.RES_UIDColumn.ColumnName, PSLibrary.Filter.SortOrderTypeEnum.None));
         resourceFilter.Fields.Add(new PSLibrary.Filter.Field(resourceDs.Resources.TableName, resourceDs.Resources.RES_NAMEColumn.ColumnName, PSLibrary.Filter.SortOrderTypeEnum.None));
         resourceFilter.Fields.Add(new PSLibrary.Filter.Field(resourceDs.Resources.TableName, resourceDs.Resources.RES_INITIALSColumn.ColumnName, PSLibrary.Filter.SortOrderTypeEnum.None));
         resourceFilter.Fields.Add(new PSLibrary.Filter.Field(resourceDs.Resources.TableName, resourceDs.Resources.RES_TYPEColumn.ColumnName, PSLibrary.Filter.SortOrderTypeEnum.None));

         PSLibrary.Filter.FieldOperator existingResource = new PSLibrary.Filter.FieldOperator(PSLibrary.Filter.FieldOperationType.Equal, resourceDs.Resources.RES_NAMEColumn.ColumnName, RES_NAME);
         resourceFilter.Criteria = existingResource;
         resourceDs = resourceSvc.ReadResources(resourceFilter.GetXml(), false);
         if (resourceDs.Resources.Count >= 1)
         {
            return resourceDs;
         }
         else
         {
            resourceDs = new SvcResource.ResourceDataSet();
            SvcResource.ResourceDataSet.ResourcesRow resourceRow = resourceDs.Resources.NewResourcesRow();
            resourceRow.RES_UID = Guid.NewGuid();
            resourceRow.RES_NAME = RES_NAME;
            resourceRow.RES_INITIALS = "LT";
            resourceDs.Resources.AddResourcesRow(resourceRow);
            resourceSvc.CreateResources(resourceDs, false, true);
            return resourceDs;
         }
      }
   }

}

Vea también

Referencia

clase Statusing

Miembros Statusing

Espacio de nombres WebSvcStatusing

SubmitStatusForResource

ReadStatusForResource