Showing posts with label New SharePoint Developer. Show all posts
Showing posts with label New SharePoint Developer. Show all posts

Tuesday, February 7, 2017

Create a Visual Studio Project, integrate with GitHub, run, and debug PowerShell Scripts just like other C# code

While we are using  Visual Studio 2015 with GitHub for all SharePoint C# projects,  we would like to manage the PowerShell or other scripts in the same way as Visual Studio projects. We could integrate the scripts with Visual Studio projects, GitHub, and be able to run and debug without leaving Visual Studio to improve developers’ productivity. Here are the procedure that will help you to set up.

1. First you need to install the Visual Studio 2015 with GitHub extension. See my previous blog for details.

2. Second you need to install PowerShell tool for visual studio 2015.

3. Third you can create the Powershell Project like the screenshot below. You can organize the folders, scripts, and documents same way as other SharePoint project as described here.


4. You can integrate the GitHub just like other C# code as described in previously blog. 

5. Now you can add command or shortcut key when right click the PowerShell script or somewhere else like the screenshot below.


You can see there is default command named "Run with PowerShell ISE" available. You can invoke the command and run PowerShell. However, everytime the code changed, you need to invoke this external UI again. Here is easy way to set up ti run the PowerShell and debug directly from Visual Studio just like the screenshot above with "Run powershell script in output window". 

The steps are described in Nick's blog.

6. Next, you need set the PowerShell execution policy using Set-ExecutionPolicy to avoid the exception. Please you need to run as admin and on the PowerShell version you are using like X86. You may also need to run the Visual Studio as admin.

Set-ExecutionPolicy RemoteSigned

7. You might need to update PowerShell config as described here to enable attaching PowerShell to some process for debugging.

Now you can enjoy developing, collaborating with GitHub, running, and debugging the PowerShell directly inside Visual Studio!

Friday, September 11, 2015

Authenticate to Office 365 and SharePoint Online option #2 - REST using SharePointOnlineCredentials object from C#

When working on SharePoint Online as a new developer, there is always some confusion how to connect and authenticate to the SharePoint site. I’m summarizing all the different authenticate ways so my developers could choice one appropriate approach for their projects.


In this blog, I’ll illustrate the C# REST example using SharePointOnlineCredentials object. In this case, you need to pass the user name, password, and the REST end point. The following example illustrated the REST API to get list from title and get all items from one list.


using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security;
using System.Threading.Tasks;
using Microsoft.SharePoint.Client;
using Newtonsoft.Json.Linq;

namespace RESTClient
{
    class Program
    {
        static void Main(string[] args)
        {
            const string siteURL = "https://mycompany.sharepoint.com/sites/SPDEV";
            const string actionREST = siteURL + "/_api/web/lists/getbytitle('TestList')";
            const string userName = "userID@mycompany.com";
            const string password = "mypassword";

            // Get the list jason result
            Task<string> result = getRestResult(siteURL, actionREST, userName, password);
            result.Wait();
            string jasonResult = result.Result;
            Console.WriteLine(jasonResult);

            // Get list Title from jason result
            var obj = JObject.Parse(jasonResult);
            var title = (string)obj.SelectToken("Title");
            Console.WriteLine(title);

            // Get all items jason result
            const string actionRESTItem = siteURL + "/_api/web/lists/getbytitle('TestList')/items";
            Task<string> resultItems = getRestResult(siteURL, actionRESTItem, userName, password);
            resultItems.Wait();
            string jasonItemResult = resultItems.Result;
            Console.WriteLine(jasonItemResult);

            // Get each item from jason result


        }

        private static async Task<string> getRestResult(string siteURL, string actionREST, string userName, string password)
        {

            //Creating SharePointOnlineCredentials 
            var securePW = new SecureString();
            foreach (var c in password) securePW.AppendChar(c);
            var credential = new SharePointOnlineCredentials(userName, securePW);

            //Creating Handler to allows the client to use SharePointOnlineCredentials
            using (var handler = new HttpClientHandler() { Credentials = credential })
            {
                //Getting authentication cookies 
                Uri uri = new Uri(siteURL);
                handler.CookieContainer.SetCookies(uri, credential.GetAuthenticationCookie(uri));

                //Invoking REST API 
                using (var client = new HttpClient(handler))
                {
                    client.DefaultRequestHeaders.Accept.Clear();
                    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                    HttpResponseMessage response = await client.GetAsync(actionREST).ConfigureAwait(false);
                    response.EnsureSuccessStatusCode();

                    string jsonData = await response.Content.ReadAsStringAsync();
                    return jsonData;
                }
            }
        }


    }
}

The nest step is to parse the jason return string to get each item details. We will provide examples in the future.

Wednesday, September 9, 2015

Authenticate to Office 365 and SharePoint Online option #1 - CSOM using SharePointOnlineCredentials object from C#


When working on SharePoint Online as a new developer, there is always some confusion how to connect and authenticate to the SharePoint site. I’m summarizing all the different authenticate ways so my developers could choice one appropriate approach for their projects.
 
In this blog, I’ll illustrate the CSOM C# example using SharePointOnlineCredentials object. In this case, you need to pass the user name and password. You need to add Microsoft.SharePoint.Client.dll and Microsoft.SharePoint.Client.Runtime.dll references.

 

using System;
using System.Security;
using Microsoft.SharePoint.Client;
 

namespace CSOM.Example
{
    class Program
    {

        static void Main(string[] args)
        { 

            // Site URL, user name, and password

            string webUrl = "https://mycompany.sharepoint.com/sites/SPDEV";

            string userName = "user@myconpony.com";

            string password = "password";
 

            // Convert the string passowrd to SecureString

            SecureString securePassword = new SecureString();

            foreach (char c in password)

            {

                securePassword.AppendChar(c);

            } 

 

            using (var context = new ClientContext(webUrl))

            {

                context.Credentials = new SharePointOnlineCredentials(userName, securePassword);

                context.Load(context.Web, w => w.Title);

                context.ExecuteQuery();

 

                Console.WriteLine("Your site title is: " + context.Web.Title); 

                var list = context.Web.Lists.GetByTitle("TestList");

                context.Load(list);

                context.ExecuteQuery();

                Console.WriteLine("Your list title is: " + list.Title);

                CamlQuery query = CamlQuery.CreateAllItemsQuery(100);

                ListItemCollection items = list.GetItems(query); 

                context.Load(items);

                context.ExecuteQuery();

                foreach (ListItem listItem in items)

                {

                    // We have all the list item data. For example, Title.

                    Console.WriteLine("Your item title is: " + listItem["Title"]);

                }

            }

        } 

    }

}

Thursday, September 3, 2015

Procedure to debug and fix error "This page can't be displayed" for provider-hosted SharePoint Add-ins

If you create an OoB provider-hosted SharePoint Add-in and run from Visual Studio, you should be able to see the default web page with “Welcome <your name>” on it.

However, we are getting the following error “This page can't be displayed” on all our development 2012 servers.


After extensive debugging, we have found a workaround for this issue and here are the steps to debug and fix it.

1. Verify TLS and SSL for browser are enabled as shown below for IE.



2. Verify the web app is inside IIS entry. The IIS configuration should be in this location C:\Users\harryc\Documents\IISExpress\config\applicationhost.xml. Check whether you have the application you developed in the configuration like below. 

 <site name="SharePointApp4Web" id="22">
                <application path="/" applicationPool="Clr4IntegratedAppPool">
                    <virtualDirectory path="/" physicalPath="C:\Projects\SharePoint2013\O365\DEV2013\SharePointApp4\SharePointApp4Web" />
                </application>
                <bindings>
                    <binding protocol="http" bindingInformation="*:44119:localhost" />
                    <binding protocol="https" bindingInformation="*:44304:localhost" />
                </bindings>
</site>


3. Verify Window system have any error as below.

In my case, the errors are:
A fatal error occurred when attempting to access the SSL server credential private key. The error code returned from the cryptographic module is 0x8009030D. The internal error state is 10001.

An error occurred while using SSL configuration for endpoint 0.0.0.0:44304.  The error status code is contained within the returned data.

4. Nest step is to verify the cert for the port number (44304) running the web. You should look at the Certificate Hash.

Run command with the port number the web is running:

IIS Cert netsh http show sslcert ipport=0.0.0.0:44304

    IP:port                      : 0.0.0.0:44304
    Certificate Hash             : ec4d6de883f60ab764f696e6a712f6694ec86b11
    Application ID               : {214124cd-d05b-4309-9af9-9caa44b2b74a}
    Certificate Store Name       : MY
    Verify Client Certificate Revocation : Enabled
    Verify Revocation Using Cached Client Certificate Only : Disabled
    Usage Check                  : Enabled
    Revocation Freshness Time    : 0
    URL Retrieval Timeout        : 0
    Ctl Identifier               : (null)
    Ctl Store Name               : (null)
    DS Mapper Usage              : Disabled
    Negotiate Client Certificate : Disabled

You can get the Certificate Hash and Application ID from above command. 

5. Verify cert on IIS directly.

You could also verify the certs to run the below command.

mmc.exe-File->Add/Remove Snapin..->Add Certificates->Select Computer account->Local Computer-OK.


Identify the certs the express 8 is using and right click Open->Details. Found the Thumprint value. This should match the value from netsh command line.

In my case, I'm getting following error "No keys found certificate!". You will understand why the provided-hosted app does not work. There is bad certificate.



We are not sure why the Visual Studio installation did not install/generate correct certificates for IIE 8 express. We are still working with Microsoft to isolate the root cause. The workaround is to change the certificate IIS Express runs against for a specific ip/port by manually deleting and re-adding the bindings via the command-line.

Here are the steps for your reference.

1. Create a self-signed certificate (i.e. “IISExpressTest”) on the server and make note of the Thumbprint value.
                Open IIS manager
                Click “Create Self-Signed Certificate…”
                Enter the name like IISExpressTest and keep Personal as store
                Right the Cert and click View
                View the details and copy the Thumbprint value like 
                    5cb2a108b853f372103294f74a12ddab0c549e6a for future step

2. From the command line do: 
netsh http show sslcert ipport=0.0.0.0:44304

    IP:port                      : 0.0.0.0:44304
    Certificate Hash             : ec4d6de883f60ab764f696e6a712f6694ec86b11
    Application ID               : {214124cd-d05b-4309-9af9-9caa44b2b74a}
    Certificate Store Name       : MY
    Verify Client Certificate Revocation : Enabled
    Verify Revocation Using Cached Client Certificate Only : Disabled
    Usage Check                  : Enabled
    Revocation Freshness Time    : 0
    URL Retrieval Timeout        : 0
    Ctl Identifier               : (null)
    Ctl Store Name               : (null)
    DS Mapper Usage              : Disabled
    Negotiate Client Certificate : Disabled
Record the Application ID for future step.

3. Determine what port a specific IIS Express site uses.  In my case, it was using 44304, so https://localhost:44304 was my site.

4. From the command line, delete the current cert.
netsh http delete sslcert ipport=0.0.0.0:44304

5. From the command line, bind the new cert.
netsh http add sslcert ipport=0.0.0.0:44304 appId={214124cd-d05b-4309-9af9-9caa44b2b74a} certhash=‎5cb2a108b853f372103294f74a12ddab0c549e6a

The port number is the port for your web running by IIS
The appId is the value you got from step #2
The certhash is the value from step #1

6. Verify https://localhost: 44304 will bring up the new certificate “IISExpressTest”.

Run the web again and you could verify the issue should be fixed and you can click the certs and view details that matches the Thumbprint value.

This workaround needs to be run for any web created and I’m thinking to add this to the Visual Studio prebuild scrip to automate the step.

Wednesday, September 2, 2015

Migrating NuGet Package Manager enabled solutions to use Automatic Package Restore

Recently I was involved to evaluate one new O365 function and there is one client Visual Project passed to me. I really want to compile this project so I can debug through the code but there are two major issues.

1. When we compile this solution, it give the following error message.
This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them.  For more information, see http://go.microsoft.com/fwlink/?LinkID=322105.

2. When we try to Manage Nuget package, we got the following error.
"Operation failed. Unable to locate solution directory. Please ensure that the solution has been saved."

After researching the issue, we found this project was NuGet Package Manager enabled solutions and we would better to migrate to NuGet Automatic Package Restore as recommended. Here is the complete procedure to rebuild the project.

1. Remove following NuGet dependencies from the project file named yourprojectname.csproj as described here. Save the project file and then you could reopen it from Visual Studio. This will resolve issue #1.

<RestorePackages>true</RestorePackages>
...
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
...

<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> <PropertyGroup> <ErrorText>This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText> </PropertyGroup> <Error Condition="!Exists('$(SolutionDir)\.nuget\NuGet.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)\.nuget\NuGet.targets'))" /> </Target>

2. Click save the project. This will resolve issue #2.

3. Right click solution and click Enable NuGet Automatic Package Restore. This will migrate to use Automatic Package Restore to avoid future NuGet package issue.

4. Right click References for the project and click Manage Nuget package. Search package required for the project such as "Active Directory Application Library". Install the package.

Now you will a project that can be compiled for debugging.

Wednesday, April 22, 2015

Powershell cmdlets to compare user's AD attributes with SharePoint user profile



When trouble shooting SharePoint user identity related issues such as UPN and SID values, it will be extremely helpful to compare the values from SharePoint with AD since SharePoint will synchronize users’ AD attributes through user profile services.  One example is some users changed their AD UPN from userid@domain.company.com to  userid@company.com and we are not sure whether this will have any impact to SharePoint. In this blog, we will provide the Powershell to query both AD and SharePoint user profile.

You could use Active Directory Explorer to view user’s AD attributes and it would be easy is to use Active Directory Cmdlets in Windows PowerShell for automation. If you have never used Active Directory Cmdlets, you should verify whether you have the feature installed by the following powershell.

Get-WindowsFeature | where displayname –like “*active dir*”

Get-WindowsFeature  rsat-AD-powershell



You could follow the instruction here to enable the AD remote powershell feature or use the powershell command to enable it.
Add--WindowsFeature  rsat-AD-powershell

This is simple example to get AD user through user CN. Please note, this will NOT work if you have multiple AD domains.


import-module activedirectory
get-module -listavailable
$wUser = "userid"

$aduser = Get-ADUser -Identity $wUser

$aduser


This is simple example to get AD user through user CN and it will work on multiple AD domains. This will also include the deleted users.
$usercn= "userid"

$ldapfilter= "(&(objectclass=user)(!objectclass=computer)(cn=" + $usercn  + "))"

$users = Get-adobject -ldapfilter $ldapfilter -server "ADController:portnumber" -IncludeDeletedObjects -properties DisplayName, userPrincipalName, cn

$users 


In order to get SharePoint user’s atttributes, you would need to configure the UPS and complete the full sync. You could use the following powershell to retrieve user’s UPN.

$userID=‘domain\userid’ 

$ca = Get-spwebapplication -includecentraladministration | where {$_.IsAdministrationWebApplication}
$spsite = $ca.url 
$site = Get-SPSite $spsite
$context = Get-SPServiceContext $site
$upsa = New-Object Microsoft.Office.Server.UserProfiles.UserProfileManager($context)
$profile = $upsa.GetEnumerator() |Where-Object {$_.AccountName -eq $userID}
$profile["SPS-UserPrincipalName"].Value 



If you found the UPN values are different after it changed form AD, you would need to run UPS full sync to sync the changes to SharePoint.