Wildcard SSL for SP and high-trust-certificate

NOTE: The certificate for  high trust does not support CNG enabled. Have to create with a legacy option.

I. Follow this to create a new certificate using for SSL:

https://support.jetglobal.com/hc/en-us/articles/235636308-How-To-Create-a-SHA-256-Self-Signed-Certificate

Example:

$cert = New-SelfSignedCertificate -DnsName “*.spdev.com” -CertStoreLocation “cert:\LocalMachine\My”

Then, go to iss web application -> bindings -> edit -> https -> SSL certificate: *.spdev.com -> host name: http://www.spdev.com -> port 443

launch the web application, on address bar, click to install the certificate to the computer

II. Follow this to create a new certificate for SP high trusted app:

https://docs.microsoft.com/en-us/sharepoint/dev/sp-add-ins/create-high-trust-sharepoint-add-ins

Example:

  1. Create a self-sign-certificate
  2. Export to pfx
  3. Export to cer
  4. Open MMC, install certificate to “Trusted Root Certificate Authority” and “Personal”
  5. On Personal, right click to the certificate -> All Tasks -> Manage Private Keys…-> Add user in your wep application pool to here
  6. Share certificate folder to everyone
  7. ……………………
  8. New-SPTrustedRootAuthority (remove first if already existed)
  9. New-SPTrustedSecurityTokenIssuer (remove first if already existed)
  10. AllowOAuthOverHttp
  11. Update OnPrem.config for all web applications
  12. IIS reset all

 

Remote to Virtual Machine on VMWare Workstation

  1. Setup your virtual machine as usual
  2. From your main machine (or any machine in your network), open the command window and type ipconfig. Then you will get something like this:Ethernet adapter vEthernet (External VM Wireless Switch) 2:

    Connection-specific DNS Suffix . :
    Link-local IPv6 Address . . . . . : fe80::14a5:1961:ba53:6c58%15
    IPv4 Address. . . . . . . . . . . : 172.27.80.62
    Subnet Mask . . . . . . . . . . . : 255.255.255.0
    Default Gateway . . . . . . . . . : 172.27.80.1

  3. Go to your virtual machine, open network and sharing center and enter like this (the subnet mask and default gateway should similar step 2). IPAddress
  4. In your VMWare Workstation, go to Virual Machine Settings and select “Bridged” as network connectionNetworkSettings.PNG
  5. Now, go back to your main machine and ping your virtual machine and make sure 0% lost like I have here 🙂Pinging 172.27.80.199 with 32 bytes of data:
    Reply from 172.27.80.199: bytes=32 time=1ms TTL=128
    Reply from 172.27.80.199: bytes=32 time=1ms TTL=128
    Reply from 172.27.80.199: bytes=32 time=1ms TTL=128
    Reply from 172.27.80.199: bytes=32 time=1ms TTL=128

    Ping statistics for 172.27.80.199:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
    Approximate round trip times in milli-seconds:
    Minimum = 1ms, Maximum = 1ms, Average = 1ms

  6. Try to remote to your virtual machine, should not be a problem now.

Config TeamCity to run UI Test on NUnit Framework

For Agent machine

  1. Install Firefox
  2. Install NUnit Adapter on Visual Studio
  3. Add Firefox path to PATH

For coding

8

For Teamcity

1. Specific agent machine for compatibility2

2. In Artifact paths of General Settings: Copy everything from Release folder to another folder (optional)3

3. Define steps

3.1 Restore packages4

3.2 Build and Package Test solution5.PNG

/p:Configuration=Release /p:Platform=”Any CPU” /p:FrameworkPathOverride=”C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1″ /p:DeployOnBuild=true;PublishProfile=PackageToZip

3.3 Update Test parameters6.PNG

echo Username::%Test.Username% > %system.teamcity.build.checkoutDir%\Test\UnitTest.CodeBase\bin\Release\Parameters.txt
echo Password::%Test.Password% >> %system.teamcity.build.checkoutDir%\Test\UnitTest.CodeBase\bin\Release\Parameters.txt
echo SiteUrl::%Test.SiteUrl% >> %system.teamcity.build.checkoutDir%\Test\UnitTest.CodeBase\bin\Release\Parameters.txt

3.4 Run UI Test in command line

Old

%system.teamcity.build.checkoutDir%\OmniaTest\UnitTest.CodeBase\bin\Release\TestWindow\vsTest.console.exe “%system.teamcity.build.checkoutDir%\OmniaTest\UnitTest.CodeBase\bin\Release\UnitTest.CodeBase.dll” /UseVsixExtensions:true

New

Turn on read/write  permission for current user on: E:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE\CommonExtensions\Microsoft\TestWindow

vsTest.console.exe %~dp0/UnitTest.CodeBase.dll /TestAdapterPath:”your packages path\Test\Dev\packages”

 

4. Define Parameters7

5. Turn on console mode in the build agent

cs stop TCBuildAgent
ping 192.0.2.2 -n 1 -w 10000 > nul

C:\BuildAgent\bin\agent.bat start

 

How to register tableau online

For researching purpose, I will use the temporary to register tableau online. The tool for generate email is: http://www.mytrashmail.com

You just need to enter your “will be” email into the register form, then click “Register” below and done.

mytrashmail

When you have your email ready, go to https://www.tableau.com, and click “Sign In”, ofcourse, you don’t have account yet, so click on “Create an account” on bellow of sign in form

Here, just enter your information with the email you registered on previous step.

tableau_createaccount

Then, click on “Create my account” and wait for its process.

Go to mytrashmail and enter your email here

tableau_checkemail1.PNG

Click the activation link and now you have access to https://www.tableau.com.

Now, you should try to use the tableau online by click into the link like this:

tableau_toonline.PNG

Check for another email

Now you can try online.tableau with something similar:

tableau_online1.PNG

 

Good luck!

How to quickly build and check your SharePoint CAML Query

Hey, I know this is a simple question: How to build a correct CAML Query and test it before put it into the code in case you don’t know deep about CAML?

Scenario:
I have a task list, with default columns and Types are:

taskcolumns

And, I also have 2 rows with dummy data like this:

AllItems

Now, I want to build the CAML Query, which returns the row math with condition: “Due Date” is “November 21” and “% Complete” is “10 %”. How to build the CAML Query and test it in this case ?

Solutions: Modify view and using SharePoint Manager
1. Modify current view by click to “Modify View” at the Ribbon

ModifyView
2. At “Filter” session, simple type what you need here, it should be easy like this:

Filter_Session
3. Click “Ok” and yeahhhh, your results will display on current view:

Result1

but wait, what I need here is the CAML Query. Where is it ?
And, SharePoint Manager is very powerful tool to help us get the CAML (and many things else). Just open the SharePoint Manager, go to your current view and look at the “Query” at properties tab, copy this, and you will have a correct CAML Query:

 <Where><And><And><Eq><FieldRef Name="PercentComplete" /><Value Type="Number">.10</Value></Eq><Geq><FieldRef Name="DueDate" /><Value Type="DateTime">2013-11-21T00:00:00Z</Value></Geq></And><Leq><FieldRef Name="DueDate" /><Value Type="DateTime">2013-11-21T00:00:00Z</Value></Leq></And></Where>  

SPManager

Happy coding!!!

Calling a WCF Service using jQuery in SharePoint

Wictor Wilén have a nice post for this article here. But I want to show you my way to create a WCF service for SharePoint

1. Add SharePoint mapped folder “ISAPI” to your project
2. In “ISAPI”, create new folder with the same name with your project name
3. Add new Web.config file into the new folder with some very basic configuration

1:  <?xml version="1.0" encoding="utf-8"?>  
2:  <configuration>  
3:   <system.serviceModel>  
4:    <behaviors>  
5:     <serviceBehaviors>  
6:     </serviceBehaviors>  
7:    </behaviors>  
8:    <bindings>  
9:    </bindings>  
10:    <services>  
11:    </services>  
12:   </system.serviceModel>  
13:  </configuration>  

4. Add new svc file with the content like this”:

1:  <%@ ServiceHost   
2:    Language="C#"   
3:    Service="My.Services.Client.NewsArticleServices, My.Services, Version=1.0.0.0, Culture=neutral, PublicKeyToken=393b1a9faf7ecfca"   
4:    Factory="Microsoft.SharePoint.Client.Services.MultipleBaseAddressWebServiceHostFactory, Microsoft.SharePoint.Client.ServerRuntime, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>  

5. In service dll, add new class named “NewsArticleServices” with content like this:

1:  using System;  
2:  using System.Collections.Generic;  
3:  using System.Linq;  
4:  using System.Text;  
5:  using System.ServiceModel;  
6:  using System.ServiceModel.Activation;  
7:  using System.ServiceModel.Web;  
8:  using Microsoft.SharePoint;  
9:  using Microsoft.SharePoint.Taxonomy;  
10:  using System.Globalization;  
11:  using System.Web;  
12:  using Microsoft.SharePoint.Utilities;  
13:  using Microsoft.SharePoint.Client.Services;  
14:  using System.Runtime.Serialization;  
15:  namespace My.Services.Client  
16:  {  
17:    [BasicHttpBindingServiceMetadataExchangeEndpointAttribute]  
18:    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]  
19:    [ServiceContract]  
20:    public class NewsArticleServices  
21:    {  
22:      [OperationContract]  
23:      [WebGet(BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Json)]  
24:      public Model.Client.News GetLatestNewsArticle()  
25:      {  
26:        Logger.LogVerbose(this, LayerNames.Services, "GetLatestNewsArticle", "Enter -->");  
27:        var result = new Model.Client.News();  
28:        try  
29:        {  
30:          var webUrl = SPContext.Current.Web.Url;  
31:          SPSecurity.RunWithElevatedPrivileges(() =>  
32:          {  
33:            using (var elevSite = new SPSite(webUrl))  
34:            {  
35:              using (var web = elevSite.OpenWeb())  
36:              {  
37:                Services.NewsArticleServices service = new Services.NewsArticleServices(web);  
38:                result = service.GetLatestNewsArticle();  
39:              }  
40:            }  
41:          });  
42:        }  
43:        catch (Exception ex)  
44:        {  
45:          Logger.LogError(this, LayerNames.Services, "GetLastedNewsArticle", "Can't get latest news article.", ex);  
46:        }  
47:        finally  
48:        {  
49:          Logger.LogVerbose(this, LayerNames.Services, "GetLatestNewsArticle", "Exit -->");  
50:        }  
51:        return result;  
52:      }  
53:    }  
54:  }  

6. Add javascript file to layouts folder with the function:

1:    function getLatestNewsArticle() {  
2:      $.ajax({  
3:        type: "GET",  
4:        url: L_Menu_BaseUrl + '/_vti_bin/YourProjectName/ClientNewsArticleServices.svc/GetLatestNewsArticle',  
5:        contentType: "application/json; charset=utf-8",  
6:        dataType: "json",  
7:        data: getParams(L_Menu_BaseUrl),  
8:        success: function (data) {  
9:          alert('Successed!');  
10:        },  
11:        error: function (err) {  
12:          alert('Failed');  
13:        }  
14:      });  
15:    }  

That’s all!

Automatic deploy wsp to SharePoint using PowerShell

1. Create a config file named “config.xml” and put it in folder “C://WspDeployment”

1:  <?xml version="1.0" encoding="utf-8"?>  
2:  <Config>  
3:   <SolutionsFolder>C:\WspDeployment\Builds\Latest</SolutionsFolder>  
4:   <WebApplication Create="FALSE">  
5:    <WebApplicationURL>http://www.yoursite.domain.base</WebApplicationURL>  
6:    <WebApplicationName>YourApplicationName</WebApplicationName>  
7:    <Port></Port>  
8:    <ApplicationPool></ApplicationPool>  
9:    <ApplicationPoolAccount></ApplicationPoolAccount>  
10:    <HostHeader></HostHeader>  
11:   </WebApplication>  
12:   <Database>  
13:    <DatabaseName></DatabaseName>  
14:    <DatabaseServer></DatabaseServer>  
15:   </Database>  
16:   <Solutions>  
17:    <Solution Scoped="FALSE">Package1.wsp</Solution>  
18:    <Solution Scoped="FALSE">Package2.wsp</Solution>  
19:    <Solution Scoped="TRUE">Package3.wsp</Solution>  
20:   </Solutions>  
21:  </Config>  

2. In the same folder of Config.xml, create new file named “WspDeployment.ps1”

1:  ## Get XML configuration file parameters  
2:  param   
3:  (  
4:    [string]$ConfigFile = $(throw '- Need parameter input file (e.g. "c:\install-config.xml")')  
5:  )  
6:  ## check to ensure Microsoft.SharePoint.PowerShell is loaded if not using the SharePoint Management Shell   
7:  $snapin = Get-PSSnapin | Where-Object {$_.Name -eq 'Microsoft.SharePoint.Powershell'}   
8:  if ($snapin -eq $null)   
9:  {    
10:       Write-Host "Loading SharePoint Powershell Snapin"    
11:       Add-PSSnapin "Microsoft.SharePoint.Powershell"   
12:  }  
13:  ## get the the node Config in the configuration file  
14:  $xmlinput = [xml] (get-content $ConfigFile)  
15:  $item = $xmlinput.Config  
16:  ## Read the Farm parameters  
17:  $SolutionsFolder = $item.SolutionsFolder  
18:  $WebApplicationURL = $item.WebApplication.WebApplicationURL  
19:  $WebApplicationName = $item.WebApplication.WebApplicationName  
20:  $Port = $item.WebApplication.Port  
21:  $ApplicationPool = $item.WebApplication.ApplicationPool  
22:  $ApplicationPoolAccount = $item.WebApplication.ApplicationPoolAccount  
23:  $HostHeader = $item.WebApplication.HostHeader  
24:  $DatabaseName = $item.Database.DatabaseName  
25:  $DatabaseServer = $item.Database.DatabaseServer  
26:  $Solutions = $item.Solutions  
27:  $Features = $item.Features  
28:  ## write the Farm parameters to the console application  
29:  Write-Host -f White "SolutionsFolder: $SolutionsFolder"  
30:  Write-Host -f White "WebApplicationURL: $WebApplicationURL"  
31:  Write-Host -f White "WebApplicationName: $WebApplicationName"  
32:  Write-Host -f White "ApplicationPool: $ApplicationPool"  
33:  Write-Host -f White "ApplicationPoolAccount: $ApplicationPoolAccount"  
34:  Write-Host -f White "HostHeader: $HostHeader"  
35:  Write-Host -f White "DatabaseName: $DatabaseName"  
36:  Write-Host -f White "DatabaseServer: $DatabaseServer"  
37:  ## this method will delete and retract the solution. You will need to call it  
38:  ## with the solution id and the webapplication. If it is globally deployed just  
39:  ## leave the web application empty  
40:  function DeleteSolution  
41:  {  
42:       param ([string]$solutionID, [string]$webApplication)  
43:       $farm = Get-SPFarm  
44:       $sol = $farm.Solutions[$solutionID]  
45:       if($sol)  
46:       {  
47:            Write-Host -f Yellow "Going to uninstall $solutionID"  
48:            if( $sol.Deployed -eq $TRUE )   
49:            {  
50:                 if ( $webApplication -eq "" )  
51:                 {  
52:                      Uninstall-SPSolution -Identity $solutionID -Confirm:0  
53:                 }  
54:                 else   
55:                 {  
56:                      Uninstall-SPSolution -Identity $solutionID -Confirm:0 -Webapplication $webApplication  
57:                 }  
58:                 while( $sol.JobExists )   
59:                 {  
60:                      Write-Host "waiting for retraction."  
61:                      sleep 3  
62:                 }  
63:            }  
64:            Write-Host -f Yellow "Going to Remove $solutionID"  
65:            Remove-SPSolution -Identity $solutionID -Force -Confirm:0  
66:            Write-Host -f Green $solutionID is deleted from this Farm  
67:       }  
68:       else  
69:       {  
70:            Write-Host -f Yellow "Solution $solutionID not found"  
71:       }  
72:  }  
73:  ## This method installs and deploys a solution based on its solution id, path and web application.  
74:  ## If the solution should be deployed globally just leave the web application empty  
75:  function DeploySolution  
76:  {  
77:       param ([string]$solutionID, [string]$solutionPath, [string]$webApplication)  
78:       $filename = $solutionPath + "\" + $solutionID  
79:       Write-Host -f White "Deploy solution $solutionID from $filename to webapplication $webApplication"  
80:       Add-SPSolution $filename  
81:       Write-Host -f Green "Solution $solutionID added"  
82:       Write-Host -f Yellow "Installing $solutionID into web application"  
83:       if ( $webApplication -eq "" )  
84:       {  
85:            Install-SPSolution –Identity $solutionID -GACDeployment -Force  
86:       }  
87:       else  
88:       {  
89:            Install-SPSolution –Identity $solutionID –WebApplication $webApplication -GACDeployment -Force  
90:       }  
91:       $farm = Get-SPFarm  
92:       $sol = $farm.Solutions[$solutionID]  
93:       if($sol -ne $null)  
94:       {  
95:            Write-Host -f Yellow "Going to install $solutionID"  
96:            while( $sol.Deployed -eq $FALSE )  
97:            {  
98:                 Write-Host "waiting for installation."  
99:                 sleep 3  
100:            }  
101:            Write-Host -f Green "Solution $solutionID is installed"  
102:       }  
103:       else  
104:       {  
105:            Write-Host -f Red "Installing $solutionID has failed. Solution is not found."  
106:       }  
107:  }  
108:  function ActivateFeature  
109:  {  
110:    param ([string]$featureID, [string]$url)  
111:    Write-Host -f Yellow "Activating feature $featureID on url $url"  
112:    $feature = Get-SPFeature -Identity $featureID  
113:    if ($feature -ne $Null)  
114:    {  
115:      try  
116:      {  
117:        if ($feature.Scope -eq "Site")  
118:        {  
119:          $feature = Get-SPFeature -Identity $featureID -Site $url  
120:        }  
121:        elseif ($feature.Scope -eq "Web")  
122:        {  
123:          $feature = Get-SPFeature -Identity $featureID -Web $url  
124:        }  
125:        elseif ($feature.Scope -eq "WebApplication")  
126:        {  
127:          $feature = Get-SPFeature -Identity $featureID -WebApplication $url  
128:        }  
129:        elseif ($feature.Scope -eq "Farm")  
130:        {  
131:          $feature = Get-SPFeature -Identity $featureID -Farm  
132:        }  
133:        else  
134:        {  
135:          $feature = $Null  
136:        }  
137:      }  
138:      catch  
139:      {  
140:        $feature = $Null  
141:      }  
142:      if ($feature -eq $Null)  
143:      {  
144:        if ($url -eq $Null)  
145:        {  
146:          Enable-SPFeature -Identity $featureID  
147:        }  
148:        else  
149:        {  
150:          Enable-SPFeature -Identity $featureID -Url $url  
151:        }  
152:        Write-Host -f Green "Feature $featureID is activated on url $url"  
153:      }  
154:      else  
155:      {  
156:        Write-Host -f Green "Feature $featureID is already activated on url $url"  
157:      }  
158:    }  
159:    else  
160:    {  
161:      Write-Host -f Red "Activating feature $featureID has failed. Feature is not found."  
162:    }   
163:  }  
164:  function DeactivateFeature  
165:  {  
166:    param ([string]$featureID, [string]$url)  
167:    Write-Host -f Yellow "Deactivating feature $featureID on url $url"  
168:    $feature = Get-SPFeature -Identity $featureID  
169:    if ($feature -ne $Null)  
170:    {  
171:      try  
172:      {  
173:        if ($feature.Scope -eq "Site")  
174:        {  
175:          $feature = Get-SPFeature -Identity $featureID -Site $url  
176:        }  
177:        elseif ($feature.Scope -eq "Web")  
178:        {  
179:          $feature = Get-SPFeature -Identity $featureID -Web $url  
180:        }  
181:        elseif ($feature.Scope -eq "WebApplication")  
182:        {  
183:          $feature = Get-SPFeature -Identity $featureID -WebApplication $url  
184:        }  
185:        elseif ($feature.Scope -eq "Farm")  
186:        {  
187:          $feature = Get-SPFeature -Identity $featureID -Farm  
188:        }  
189:        else  
190:        {  
191:          $feature = $Null  
192:        }  
193:      }  
194:      catch  
195:      {  
196:        $feature = $Null  
197:      }  
198:      if ($feature -ne $Null)  
199:      {    
200:        if ($url -eq $Null)  
201:        {  
202:          Disable-SPFeature -Identity $featureID -Force -Confirm:$false  
203:        }  
204:        else  
205:        {  
206:          Disable-SPFeature -Identity $featureID -Url $url -Force -Confirm:$false  
207:        }  
208:        Write-Host -f Green "Feature $featureID is deactivated on url $url"  
209:      }  
210:      else  
211:      {  
212:        Write-Host -f Green "Feature $featureID was already deactivated on url $url"  
213:      }  
214:    }  
215:    else  
216:    {  
217:      Write-Host -f Red "Deactivating feature $featureID has failed. Feature is not found."  
218:    }  
219:  }  
220:  ## get the web application and if not exist add it based on the data from the config.xml file  
221:  $webApp = Get-SPWebApplication $WebApplicationURL -ea SilentlyContinue   
222:  $doCreate = $item.WebApplication.GetAttribute("Create")  
223:  if ($webApp -eq $Null -and $doCreate -eq $TRUE)  
224:  {  
225:       Write-Host -f Yellow "No web application found. Web application is created"  
226:       New-SPWebApplication -Name $WebApplicationName -ApplicationPool $ApplicationPool -ApplicationPoolAccount $ApplicationPoolAccount -Port $Port -URL $WebApplicationURL -HostHeader $HostHeader -DatabaseName $DatabaseName -DatabaseServer $DatabaseServer  
227:       $webApp = Get-SPWebApplication $WebApplicationURL -ea SilentlyContinue  
228:  }  
229:  ## start retract, delete, install and deploy all solutions found in the config xml file. When the  
230:  ## Scoped atrribute is set to true, the solution is retracted and deployed globally  
231:  if ($webApp -ne $Null)  
232:  {  
233:    Write-Host -f Green "Web application is created/present"  
234:       foreach($solution in $Solutions.ChildNodes)  
235:       {  
236:            $scoped = $solution.GetAttribute("Scoped")  
237:            $solutionName = $solution.InnerText  
238:            if ($scoped -eq $TRUE)  
239:            {  
240:                 Write-Host -f White "Solution $solutionName is scoped"  
241:                 DeleteSolution -solutionID $solutionName -webApplication $WebApplicationURL  
242:            }  
243:            else  
244:            {  
245:                 Write-Host -f White "Solution $solutionName is not scoped"  
246:                 DeleteSolution -solutionID $solutionName -webApplication ""  
247:            }  
248:       }  
249:       foreach($solution in $Solutions.ChildNodes)  
250:       {  
251:            $scoped = $solution.GetAttribute("Scoped")  
252:            $solutionName = $solution.InnerText  
253:            if ($scoped -eq $TRUE)  
254:            {  
255:                 Write-Host -f White "Solution $solutionName is scoped"  
256:                 DeploySolution -solutionID $solutionName -solutionPath $SolutionsFolder -webApplication $WebApplicationURL  
257:            }  
258:            else  
259:            {  
260:                 Write-Host -f White "Solution $solutionName is not scoped"  
261:                 DeploySolution -solutionID $solutionName -solutionPath $SolutionsFolder -webApplication ""  
262:            }  
263:       }  
264:       if ($Features -ne $Null)  
265:       {  
266:            foreach($feature in $Features.ChildNodes)  
267:            {  
268:                 $featureUrl = $feature.GetAttribute("Url")  
269:                 DeactivateFeature -featureID $feature.InnerText -url $featureUrl  
270:            }  
271:            foreach($feature in $Features.ChildNodes)  
272:            {  
273:                 $featureUrl = $feature.GetAttribute("Url")  
274:                 ActivateFeature -featureID $feature.InnerText -url $featureUrl  
275:            }  
276:       }  
277:  }  

3. Put all wsps in to the folder “C://WspDeployment/Builds/Latest/”
4. Open the SharePoint Management shell and type

1:  cd "C:\WspDeployment\"  
2:  .\WspDeployment.ps1 -configfile config.xml  

Done!!!

Deploy SharePoint MVC App to Azure

Can we use ASP.NET MVC 4 for an App for SharePoint? Yes, we can. And bspann already gave us a very good details how to do this here. So, I do not talk about this again. What I want to say here is how can we develop and deploy an app on both “developer machine” and  “Azure” in same project. The scenario here is my developer machine using server-to-server to create a high trust app, and use a client secret in Azure.

My solution for this is using Web.config Transformation, which can help you develop and deploy your MVC web in somewhere. Here is the steps:

1. At the “Solution Configuration” of Visual Studio 2012, click into a “Configuration Manager…”

2. In “Configuration Manager”, click “New” and provide it a name

3. Right click on the “Web.config” in your MVC and select “Add Config Transform”

4. Now, you will see the new transform of this web.config named “web.AzureDebug.config”. Open the web.config and put some config in your appSeting like this:

1:   <appSettings>  
2:    <add key="webpages:Version" value="2.0.0.0"/>  
3:    <add key="webpages:Enabled" value="false"/>  
4:    <add key="PreserveLoginUrl" value="true"/>  
5:    <add key="ClientValidationEnabled" value="true"/>  
6:    <add key="UnobtrusiveJavaScriptEnabled" value="true"/>  
7:    <add key="ProductID" value="6d510a27-38f7-4d0f-9e67-123456789012"/>  
8:    <add key="ClientSigningCertificatePath" value="C:\MyCert\HighTrustSampleCert.pfx"/>  
9:    <add key="ClientSigningCertificatePassword" value="yourP@ssw0rd"/>  
10:    <add key="IssuerId" value="8650ec6b-4e14-4747-9f8a-123456789012"/>  
11:    <add key="ClientId" value="6f8e094b-d6e6-40c4-b3b7-123456789012"/>  
12:    <add key="ClientSecret" value="AbCdEfGhIjKlMnOpQrAyxfU8zdZ+hAdT2wmu6ceuaJvkzfPnJQ="/>  
13:    <add key="DatabaseConnectionString" value="metadata=res://*/YourDatabase.csdl|res://*/YourDatabase.ssdl|res://*/YourDatabase.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=.;initial catalog=YourDatabase;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;"/>  14:    <add key="RemoteEndpoint" value="http://localhost:8888"/>  
15:    <add key="SharePointSiteUrl" value="http://sp/sites/online"/>  
16:    <add key="ServiceConfiguration" value="Local"/>  
17:   </appSettings>  

5. Open the “web.Debug.config” and edit the “system.web” to remove attributes from “release” and “azuredebug”

1:   <system.web>  
2:    <compilation xdt:Transform="RemoveAttributes(release,azuredebug)" />  
3:   </system.web>  

And, of course, edit appSettings

1:   <appSettings>  
2:    <add key="HostedAppHostNameOverride" xdt:Transform="Remove" xdt:Locator="Match(key)" />  
3:    <add key="ClientSigningCertificatePath" value="C:\MyCert\HighTrustSampleCert.pfx" xdt:Transform="Replace" xdt:Locator="Match(key)"/>  
4:    <add key="ClientSigningCertificatePassword" value="khongbiet_1" xdt:Transform="Replace" xdt:Locator="Match(key)"/>  
5:    <add key="IssuerId" value="8650ec6b-4e14-4747-9f8a-123456789012" xdt:Transform="Replace" xdt:Locator="Match(key)"/>  
6:    <add key="ClientId" value="6f8e094b-d6e6-40c4-b3b7-123456789012" xdt:Transform="Replace" xdt:Locator="Match(key)"/>  
7:    <add key="ClientSecret" value="AbCdEfGhIjKlMnOpQrAyxfU8zdZ+hAdT2wmu6ceuaJvkzfPnJQ=" xdt:Transform="Replace" xdt:Locator="Match(key)"/>  
8:    <add key="DatabaseConnectionString" value="metadata=res://*/YourDatabase.csdl|res://*/YourDatabase.ssdl|res://*/YourDatabase.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=.;initial catalog=YourDatabase;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" xdt:Transform="Replace" xdt:Locator="Match(key)"/>  9:    <add key="RemoteEndpoint" value="http://localhost:8888" xdt:Transform="Replace" xdt:Locator="Match(key)"/>  
10:    <add key="SharePointSiteUrl" value="http://sp/sites/online" xdt:Transform="Replace" xdt:Locator="Match(key)"/>  
11:    <add key="ServiceConfiguration" value="Local" xdt:Transform="Replace" xdt:Locator="Match(key)"/>  
12:   </appSettings>  

6. Open the “web.AzureDebug.config” and edit it the same way we did for “web.Debug.config”

In “system.web”

1:   <system.web>  
2:    <compilation xdt:Transform="RemoveAttributes(debug,release)" />  
3:   </system.web>  

In “appSettings”

1:   <appSettings>  
2:    <add key="HostedAppHostNameOverride" xdt:Transform="Remove" xdt:Locator="Match(key)" />  
3:    <add key="ClientSigningCertificatePath" xdt:Transform="Remove" xdt:Locator="Match(key)" />  
4:    <add key="ClientSigningCertificatePassword" xdt:Transform="Remove" xdt:Locator="Match(key)" />  
5:    <add key="IssuerId" xdt:Transform="Remove" xdt:Locator="Match(key)"/>  
6:    <add key="ClientId" value="48384dfb-52f9-4f04-9a53-123456789012" xdt:Transform="Replace" xdt:Locator="Match(key)"/>  
7:    <add key="ClientSecret" value="AbCdEfGhIjKlMnOpQrAyxfU8zdZ+Ulemc9Z6NM6TTKn51Xwu7/o=" xdt:Transform="Replace" xdt:Locator="Match(key)"/>  
8:    <add key="DatabaseConnectionString" value="metadata=res://*/YourDatabase.csdl|res://*/YourDatabase.ssdl|res://*/YourDatabase.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=tcp:quacquac.database.windows.net,1433;initial catalog=YourDatabase;persist security info=True;user id=khetkhet@quacquac;password=oeoe;MultipleActiveResultSets=True;App=EntityFramework&quot;" xdt:Transform="Replace" xdt:Locator="Match(key)"/>  9:    <add key="RemoteEndpoint" value="https://yourappsite.cloudapp.net" xdt:Transform="Replace" xdt:Locator="Match(key)" />  
10:    <add key="SharePointSiteUrl" value="https://yoursharepointsite.sharepoint.com/sites/online" xdt:Transform="Replace" xdt:Locator="Match(key)" />  
11:    <add key="ServiceConfiguration" value="Cloud" xdt:Transform="Replace" xdt:Locator="Match(key)" />  
12:   </appSettings>  

7. Rebuild your solutions to make sure everything is ok.

8. If you want to deploy your app to local, select “Debug” in “Configuration Manager” and rebuild. Then, right click on your app project and select “Publish…”. In “Publish Web” dialog, select “Profile” tab and create new profile named “MVCDebug”. At the second tab, choose the publish method and target location

Select “Debug” in configuration

Click “Publish” to publish your MVC web

9. In case you want to deploy it to Azure, you need to create new project type “Windows Azure Cloud Service”, do not select anything and click “OK”

Then, add “web role project in solution”

and select your MVC project

10. Rebuild your solutions with “AzureDebug” then right click on your AzureProject and select “Publish…”

10. Fill some information and click into “Publish”

Done!!!