How to created Project Server in Sharepoint Project Server

How to created Project Server in Sharepoint Project Server

Song Nghia - Technical Consultant


private void createproject_Click (object sender, EventArgs e)

{

           // create PWA context

           projContext = new ProjectContext(pwaPath);

    

           // Access with default logged in credentials

           projContext.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;

            try

             {               

                ProjectCreationInformation newProj = new ProjectCreationInformation();

                newProj.Id = Guid.NewGuid();

                newProj.Name = txtProjectName.Text;

                newProj.Description = txtProjectDesc.Text;

                newProj.Start = DateTime.Today.Date;

                newProj.EnterpriseProjectTypeId = GetEptUid(basicEpt);

                PublishedProject newPublishedProj = projContext.Projects.Add(newProj);

                QueueJob qJob = projContext.Projects.Update();

                projContext.Load(qJob);

                projContext.Load(projContext.Projects);

                projContext.ExecuteQuery();

                JobState jobState = projContext.WaitForQueue(qJob, timeoutSeconds);

                label1.ForeColor = Color.Green;

                label1.Text = "Successfully created project-" + txtProjectName.Text;

                txtProjectDesc.Text = "";

                txtProjectName.Text = "";

                //LoadProjects(projContext);

            }
            catch (Exception ex)
            {

                label1.ForeColor = Color.Red;

                label1.Text = ex.Message.ToString();

            }

        }
        //Get/Read the GUID of the specified enterprise project type.

        private static Guid GetEptUid(string eptName)

        {

            Guid eptUid = Guid.Empty;

            try

            {

               projContext.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
                var eptList = projContext.LoadQuery(

                    projContext.EnterpriseProjectTypes.Where(

                        ept => ept.Name == eptName));

                projContext.ExecuteQuery();

                eptUid = eptList.First().Id;

            }

            catch (Exception ex)

            {
                string msg = string.Format("GetEptUid: eptName = \"{0}\"\n\n{1}",eptName, ex.GetBaseException().ToString());
                throw new ArgumentException(msg);
            }
            return eptUid;
        }
How to assign task in C# OM Porject Server

How to assign task in C# OM Porject Server

Song Nghia - Technical Consultant

private void assignResource_Click(object sender, EventArgs e)

        {
            // create PWA context

            projContext = new ProjectContext(pwaPath);

            // Access with default logged in credentials

            projContext.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;

            projContext.Load(projContext.Projects);

            projContext.ExecuteQuery();

            // pass project GUID in place of combo box selection

            PublishedProject pubProject = projContext.Projects.GetByGuid(Guid.Parse(comboProjects.SelectedValue.ToString()));

            projContext.Load(pubProject);

            projContext.ExecuteQuery();
            projContext.Load(projContext.EnterpriseResources);

            projContext.ExecuteQuery();

            int numResInCollection = projContext.EnterpriseResources.Count();

            Microsoft.SharePoint.Client.User getUser = projContext.Web.SiteUsers.GetByLoginName
            ("i:0#.w|xxx\\xxx"); // Replace with your user

            EnterpriseResource userRes = projContext.EnterpriseResources.GetByUser(getUser);

            projContext.Load(userRes);

            projContext.ExecuteQuery();

            DraftProject projectDraft = pubProject.CheckOut();

            projContext.Load(projectDraft.Tasks);

            projContext.ExecuteQuery();

            DraftTaskCollection taskCollection = projectDraft.Tasks;

            foreach (DraftTask task in taskCollection)
            {
                if (numResInCollection > 0)
                {

                    if (task.Name == comboTaskList.SelectedItem.ToString()) // Replace with specific task

                    {
                        //task.Duration = "5d";

                        AssignmentCreationInformation assignment = new AssignmentCreationInformation();

                        assignment.Id = Guid.NewGuid();

                        assignment.TaskId = task.Id;

                        assignment.ResourceId = userRes.Id;

                        task.Assignments.Add(assignment);

                        projectDraft.Assignments.Add(assignment);

                        projectDraft.Update();

                    }

                }

            }

            projContext.ExecuteQuery();

            projectDraft.Publish(true);

            //QueueJob qJob = projContext.Projects.Update();

            //JobState jobState = projContext.WaitForQueue(projContext.Projects.Update(), 10);

            projectDraft.CheckIn(true);

            projContext.ExecuteQuery();
        }
How to Check Use SharePointOnlineCredentials for SharePoint Online and NetworkCredential in other case.

How to Check Use SharePointOnlineCredentials for SharePoint Online and NetworkCredential in other case.


Song Nghia - Technical Consultant

var siteUrl = "https://sharepointsiteurl";
// Login
var userLogin = "userLogin@domain";
// Password
var userPassword = "P@ssw0rd";

var pwd = new SecureString();
foreach (var c in userPassword) pwd.AppendChar(c);
var SPOCredentials = new SharePointOnlineCredentials(userLogin, pwd);
var SPCredentials = new NetworkCredential(userLogin, pwd);

using (var ctx = new ClientContext(siteUrl))
{
    try
    {
        // try to use SharePoint Online Credentials
        ctx.Credentials = SPOCredentials;
        ctx.ExecuteQuery();
    }
    catch (ClientRequestException)
    {
        // switch to NetworkCredential
        ctx.Credentials = SPCredentials;
        ctx.ExecuteQuery();
    }
    catch (NotSupportedException)
    {
        // switch to NetworkCredential
        ctx.Credentials = SPCredentials;
        ctx.ExecuteQuery();
        Console.WriteLine("SharePoint On-premise");
    }

    // Working with SharePoint Data
}
How to create task in Sharepoint Project Server

How to created task in  Sharepoint Project Server 


Song Nghia - Technical Consultant

        private void createTask_Click(object sender, EventArgs e)
        {

            // create PWA context

            projContext = new ProjectContext("http://sharepoint.votivasoft.com:81/PWA/");

            // Access with default logged in credentials

            projContext.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;

            try
            {

                projContext.Load(projContext.Projects);

                projContext.ExecuteQuery();

                // pass project GUID in place of combo box selection

                PublishedProject pubProject = projContext.Projects.GetByGuid(Guid.Parse(comboProjects.SelectedValue.ToString()));

                projContext.Load(pubProject);

                var job = projContext.Projects.Update();

                projContext.ExecuteQuery();

                DraftProject projectDraft = pubProject.CheckOut();

                TaskCreationInformation taskCreation = new TaskCreationInformation();

                taskCreation.Name = txtTaskName.Text;

                taskCreation.Start = dateTimeStart.Value;

                taskCreation.Finish = dateTimeFinish.Value;

                taskCreation.Id = Guid.NewGuid();

                taskCreation.Duration = txtDuration.Text;

                taskCreation.IsManual = true;

                projectDraft.Tasks.Add(taskCreation);

                projectDraft.Update();

                projectDraft.Publish(true);

                if (WaitForJob(projContext, job))

                {

                    //label1.Text = "Task Created";

                }

                else

                {
                    label1.Text = "Task failed";

                }

                projectDraft.CheckIn(true);

                projContext.ExecuteQuery();

            }

            catch (Exception ex)

            {

            }

        }
S4. Adding and Removing Fields(Column in C#)

S4. Adding and Removing Fields(Column in C#)

Song Nghia - Technical Consultant

1. Overview

2. Removing field in list
3. Adding field in list

4.Search google: sharepoint field xml schema date

5. Look llke insert control -> code now



S2. Add Remove List in Sharepoint by C#

S2. Add Remove List in Sharepoint by C# 

Song Nghia - Technical Consultant
1. Overview

- ListCreationInfomation: List object return from sharepoint like Project, Task, employee…





2. Adding list to sharepoint:
3.  Adding list to sharepoint:


Connect Sharepoint and develop from C# base on Object Model.

Connect Sharepoint and develop from C# base on Object Model.

Song Nghia - Technical Consultant

HI all,

In this tutorial, we will explore how to connect and configure C# to Sharepoint.

It work on Sharepoint 2013 and older version.

S1. Connect Sharepoint get public info


1. Get file DLL intergrade from program file

- Link: C:\Program files\commom files\Miscrosoft shared\ Web server Extensions\[version 13 or 16]\ISAPI\ [Microsoft.Sharepoint.Client.dll and Microsoft.Sharepoint.Client.Runtime.dll]

- Select 2 file dll and referent C# project to this.
2. Connect sharepoint with public info

How to improve performance Dynamic AX 2012

How to improve performance Dynamic AX 2012

Solution 1: Check tables take a long time to excute query. So it become statics table.
Song Nghia - Technical Consultant

Look like:
You can check tables takes long time to excute from trace parses:


Solution 2: Check missing index and update index table.

Step1: Restart AOS and SQL
Step2: Your process
Step3: Run script to check what you need to improve.

SELECT CAST(SERVERPROPERTY('ServerName') AS [nvarchar](256)) AS [SQLServer] ,
       db.[database_id] AS [DatabaseID] ,
       db.[name] AS [DatabaseName] ,
       id.[object_id] AS [ObjectID] ,
       id.[statement] AS [FullyQualifiedObjectName] ,
       id.[equality_columns] AS [EqualityColumns] ,
       id.[inequality_columns] AS [InEqualityColumns] ,
       id.[included_columns] AS [IncludedColumns] ,
       gs.[unique_compiles] AS [UniqueCompiles] ,
       gs.[user_seeks] AS [UserSeeks] ,
       gs.[user_scans] AS [UserScans] ,
       gs.[last_user_seek] AS [LastUserSeekTime] ,
       gs.[last_user_scan] AS [LastUserScanTime] ,
       gs.[avg_total_user_cost] AS [AvgTotalUserCost] ,
       gs.[avg_user_impact] AS [AvgUserImpact] ,
       gs.[system_seeks] AS [SystemSeeks] ,
       gs.[system_scans] AS [SystemScans] ,
       gs.[last_system_seek] AS [LastSystemSeekTime] ,
       gs.[last_system_scan] AS [LastSystemScanTime] ,
       gs.[avg_total_system_cost] AS [AvgTotalSystemCost] ,
       gs.[avg_system_impact] AS [AvgSystemImpact] ,
       gs.[user_seeks] * gs.[avg_total_user_cost] * (gs.[avg_user_impact] * 0.01) AS [IndexAdvantage] ,
       OBJECT_NAME(id.[object_id], db.[database_id]) [Table Name] ,
       'CREATE INDEX [Missing_IXNC_' + OBJECT_NAME(id.[object_id], db.[database_id]) + '_' + REPLACE(REPLACE(REPLACE(ISNULL(id.[equality_columns], ''), ', ', '_'), '[', ''), ']', '') + CASE
                                                                                                                                                                                             WHEN id.[equality_columns] IS NOT NULL
                                                                                                                                                                                                  AND id.[inequality_columns] IS NOT NULL THEN '_'
                                                                                                                                                                                             ELSE ''
                                                                                                                                                                                         END + REPLACE(REPLACE(REPLACE(ISNULL(id.[inequality_columns], ''), ', ', '_'), '[', ''), ']', '') + '_' + LEFT(CAST(NEWID() AS [nvarchar](64)), 5) + ']' + ' ON ' + id.[statement] + ' (' + ISNULL(id.[equality_columns], '') + CASE
                                                                                                                                                                                                                                                                                                                                                                                                                             WHEN id.[equality_columns] IS NOT NULL
                                                                                                                                                                                                                                                                                                                                                                                                                                  AND id.[inequality_columns] IS NOT NULL THEN ','
                                                                                                                                                                                                                                                                                                                                                                                                                             ELSE ''
                                                                                                                                                                                                                                                                                                                                                                                                                         END + ISNULL(id.[inequality_columns], '') + ')' + ISNULL(' INCLUDE (' + id.[included_columns] + ')', '') AS [ProposedIndex] ,
                                                                                                                                                                                                                                                                                                                                                                                                                               CAST(CURRENT_TIMESTAMP AS [smalldatetime]) AS [CollectionDate]
FROM [sys].[dm_db_missing_index_group_stats] gs WITH (NOLOCK)
INNER JOIN [sys].[dm_db_missing_index_groups] ig WITH (NOLOCK) ON gs.[group_handle] = ig.[index_group_handle]
INNER JOIN [sys].[dm_db_missing_index_details] id WITH (NOLOCK) ON ig.[index_handle] = id.[index_handle]
INNER JOIN [sys].[databases] db WITH (NOLOCK) ON db.[database_id] = id.[database_id]
WHERE id.[database_id] > 4 -- Remove this to see for entire instance
ORDER BY [IndexAdvantage] DESC OPTION (RECOMPILE);
result: 
And then: excute proposedindex and check performance again
Solution 3: make temp in sql.
How to use Microsoft Dynamics AX 2012 Trace Parser

How to use Microsoft Dynamics AX 2012 Trace Parser

Song Nghia - Technical Consultant

Noted: You need install trace passer tool when setup or resetup AX 2012

Microsoft Dynamics AX 2012 Trace Parser is a wonderful tool which can help you in identifying fairly good amount of performance problems within your installations. 
So what is Microsoft Dynamics AX 2012 Trace Parser??

Trace Parser provides user interfaces to import, process and render ETW tracing events that produced by Microsoft Dynamics AX. User can then analyze tracing events to identify performance bottlenecks such as long-running X++ methods, slow SQL queries and frequently called RPCs. Features in Trace Parser help users determine the root causes of performance problems.


So how do we install and setup trace parser

Bit of things which we need to note when we do this install

Microsoft Dynamics AX 2012 setup program provides Trace parser as an install. Note that Trace Parser requires .Net Business Connector. In order to run Trace Parser, you also

need access to a SQL Server 2008 instance (Enterprise or Developer edition) with admin permission. Using a local SQL server instance is recommended. You don’t need to use the same SQL instance where the AX DB is installed.

It is quite boring to explain the installation process of any utility so try it yourself and let us know if you have any issues.

So how does it work???

It can be used for collecting and analyzing traces as below.

Start Microsoft Dynamics AX 2012 client and switch to Development Workspace. Open the Tracing cockpit (in the Tools menu) form:

To collect trace:

Click “Start trace”, specify a trace file name. Event tracing is now enabled in AX.
“Replay” the scenario that you are investigating in AX client. Once done, click the “Stop trace” button in Tracing Cockpit a trace file is now created.
You may now click the “Open trace” button to launch a new Trace Parser instance and imports the trace automatically
Please keep in mind when you do a Trace collection:

Keep the trace scenarios as short as possible to ensure that traces are much appropriate.
Open trace tool and import file within senario.

You can import the trace parser results what you had collected from your client as below

result when you see sql and table.

You can excute sql to check why select or query table takes a long time


Particular financial dimension mandatory on a form in AX 2012

Particular financial dimension mandatory on a form in AX 2012

Song Nghia - Technical Consultant

We may come across mandate particular financial dimension on particular form.


Here is the process to mandate Department dimension for customers.



Am using event handlers introduced in AX 2012 to achieve this.
Go through the below link to understand better on Event handlers.



Step1.  Create a new Class with the name ‘CustTableEventHandler’
Step2. Create a new Pre-or post-event handler method as shown below


step3. Rename newly created method as ‘custValidateWrite’ and write logic as shown below.

public static void custValidateWrite(XppPrePostArgs _args)
{
    DimensionAttribute                  dimAttr;
    DimensionAttributeValue             dimAttrValue;
    DimensionAttributeValueSetItem      dimAttrValueSetItem;
    CustTable                           custTable;
    RefRecId                            defaultDimension;
    boolean                             ret;
    ;

    custTable   = _args.getThis();
    ret         = _args.getReturnValue();

    defaultDimension    =   custTable.DefaultDimension;
   
    dimAttr             =   DimensionAttribute::findByName('Department');

    select firstonly RecId, DisplayValue from dimAttrValueSetItem
                where dimAttrValueSetItem.DimensionAttributeValueSet == defaultDimension
            join dimAttrValue
                where dimAttrValue.RecId == dimAttrValueSetItem.DimensionAttributeValue &&
                dimAttrValue.DimensionAttribute == dimAttr.RecId       &&
                dimAttrValue.IsDeleted == false;
   
    if (!dimAttrValueSetItem.DisplayValue)
    {
        ret     = checkFailed("Department must be specified.");
    }

    _args.setReturnValue(ret);
}

step 4. Go to ‘validateWrite’ method of CustTable then right click & select New event handler subscription as shown below.


Step5. Go to the properties of newly created event handler method & set the properties as shown below.
Step6. Now try to create new customer without department then it throws a message saying that ‘Department must be specified.’


Sent mail template HTML AX 2012

Sent mail template HTML AX 2012

Song Nghia - Technical Consultant

private void sendMail()
{
    SysEmailRecipients          recipientEmail;
    HcmWorker                   hcmWorker = HcmWorker::find(worker);
    HcmWorker                   hcmWorkerMan;
    Email                       workerManEmail;
    Name                        wokerName;
    Map                         mappings;
    int                         i;
    VhpOTRegistrationTable      regTable  = VhpOTRegistrationTable::find(regNo);
    str                         regLine;
    container                   listWorker = VhpAbsenceWorkerApproval::getManagerApprovalByWoker(worker);
    VhpAbsenceWorkerApproval    absenceWorkerApproval;
    ;

    if(regTable.status ==  VhpOTRegistrationTableStatus::confirmed || regTable.status ==  VhpOTRegistrationTableStatus::approved)
    {
            //Get recipient Email manage
            for(i = 1; i <= conLen(listWorker); i++)
            {

                hcmWorkerMan = HcmWorker::find(conPeek(listWorker, i));
                absenceWorkerApproval = VhpAbsenceWorkerApproval::find(hcmWorkerMan.RecId, HcmEmploymentAbsenceSetup::findByEmployment(HcmEmployment::findByWorkerLegalEntity(worker, CompanyInfo::current()).RecId).AbsenceSetupId);

                if(absenceWorkerApproval.SendMail)
                {
                    workerManEmail = hcmWorkerMan.email();
                    if(workerManEmail)
                    {
                        if(!recipientEmail)
                        {
                            recipientEmail = workerManEmail;

                            wokerName = hcmWorkerMan.name();

                        }
                        else
                        {
                            recipientEmail += strFmt("%1 %2", ";", workerManEmail);

                            wokerName += strFmt("%1 %2", ";", hcmWorkerMan.name());

                        }
                    }
                }
            }
    }
    else
    {
        recipientEmail = hcmWorker.email();
        wokerName = hcmWorker.name();
    }

    if(recipientEmail && emailId)
    {
        // Build your variable/text mappings
        mappings = new Map(Types::String, Types::String);
        mappings.insert('Status', enum2str(regTable.status));
        mappings.insert('UserName', wokerName);
        mappings.insert('RequestNo', regNo);
        mappings.insert('RegNote', regTable.registrationNote);
        regLine = this.getOverTimeLine();
        mappings.insert('RegLine', regLine);

        SysEmailTable::sendMail(emailId, //Template

                                SysEmailTable::find(emailId).DefaultLanguage, // Chosen language

                                recipientEmail, // Who you're sending the email to

                                mappings, // Your variable mappings

                                "", // Location of file attachment (server/client matters) or none

                                "", // XML if you're using XSLT

                                true, // Traceable or not?

                                curUserId(),  // Sending user

                                true); // Use retries?

    }
}
Difference between Transfer Journal ,Transfer Order and Stock Transfer?

Difference between Transfer Journal ,Transfer Order and Stock Transfer?

Song Nghia - Technical Consultant
What is the difference between a transfer journal and a transfer order? 
- With the help of the transfer journal, the Inventory Manager transfers the items from one dimension (warehouse, location, color, etc) to another one instantaneously.

The transfer order is used for registering in the system the items that must be moved from one warehouse to another and for managing this process. 

Process Includes:
Create Transfer Order
Pick Items to Transfer->then->Picking list registeration
or
Pick Items to Transfer(No Picking list registeration)
Ship Transfer Order
Receive the Items at other end.

Add HTML into a Report (Report Builder and SSRS)

Add HTML into a Report (Report Builder and SSRS)


Song Nghia - Technical Consultant
Using a placeholder, you can import HTML from a field in your dataset for use in the report. By default, a placeholder represents plain text, so you will need to change the placeholder mark-up type to HTML. For more information, see Importing HTML into a Report (Report Builder and SSRS).
 Note
You can create and modify paginated report definition (.rdl) files in Report Builder and in Report Designer in SQL Server Data Tools. Each authoring environment provides different ways to create, open, and save reports and related items.

To add HTML from a field in your dataset into a text box

  1. On the Insert tab, click List. Click the design surface, and then drag to create a box that is the size you want.
    The Dataset Properties dialog box opens. You can use a shared dataset or a dataset embedded in your report. For more information, click Dataset Properties Dialog Box, Query (Report Builder) or Dataset Properties Dialog Box, Query.
  2. On the Insert tab, click Text Box. Click in the list, and then drag to create a box that is the size you want.
  3. Drag an HTML field from your dataset into the text box. A placeholder is created for your field.
  4. Right-click the placeholder, and then click Placeholder Properties.
  5. On the General tab, verify that the Value box contains an expression that evaluates to the field you dropped in step 3.
  6. Click HTML - Interpret HTML tags as styles. This causes the field to be evaluated as HTML.
  7. Click OK.
Refresh selectpicker boostrap 4.

Refresh selectpicker boostrap 4.

Song Nghia - Technical Consultant

Select picker boostrap usually have issues. 

This is the best way to append or html oftion to select.

$('#projectFilter').selectpicker('refresh').empty().append(listOftionHtml).selectpicker('refresh').trigger('change');


Alternate key & Replacement key

Alternate key & Replacement key


The standard application is full of practical and real-life examples. One of them is HcmWorker table. The primary key of this table is the surrogate key, i.e. RecId.
But it also has two unique keys, that could be used as the primary key, therefore they're alternate keys.
One of them, HcmWorker_AX2, contains a human-readable value, namely the personnel number. That's a good choice when we want to display something to users, allow them to select a worker from a lookup and so on. Working with the primary key, RecId, wouldn't make sense, so we set HcmWorker_AX2 as the replacement key, and it will be automatically used by reference group controls.