Fabian Williams SharePoint Blog

Solving problems with SharePoint day and night

SQL Azure to EF5 to OData to BCS EL


So yesterday, I was talking with Ted Pattison as he did a Critical Path class on the Great SharePoint Adventure (GSA) and a question was asked by one of his students about using Entity Framework to connect to a Oracle Database and then make an External Content Type and External List.  I suggested that you can use various Database Technologies to connect to your backend Data and serve it up. in this case I am connecting to a SQL Azure Data in this case Northwind Customers and I will be using ADO.NET Entity Framework to work with it. I will then use WCF Data Service to render this data into OData format and use that URI as a source for my External Content Type in a Visual Studio SharePoint App.

In all of this I will be targeting a SharePoint Online Instance, but this can be used for On Prem, in fact the way i do my example I would either need to have (1) set up my SPO for Hybrid Inbound or it wouldn’t work because my URI is internally hosted, I could of course (2) do a Azure Cloud Service [as i have done in previous posts] as well.

Grab the Code here: http://code.msdn.microsoft.com/SQL-Azure-to-EF5-to-OData-2b2bd362

How To

For this you will need a Visual Studio Solution with two projects. One will be for the ASP.NET project that will make the connection to the SQL Azure Data and host it, alternatively this could be a Web Role Project targeting a Cloud Service in Azure. The second project will be a SharePoint App Model Project that will create the External Content Type.

Create a ASP.NET Project



As you can see above we are creating a project of an ASP.NET Empty Web Application.  So, we are also targeting a SQL Azure Database, i want to show that to you, see below


We will be targeting a Database called FabianNorthWind


Above what you see is us adding a ADO.NET Entity Model to the project to connect to the Azure SQL Instance.


Follow the wizard through and you should see what I see here


Finally you will have your EF in your project


Save your project here and next we will have to add a WCF Data Service, we do this so we can have a URI to connect to that will expose the SQL Azure Data, or Oracle Data etc.


Above is our URI endpoint and it is at NWindCustomer.svc

Once you do that you will get a template helper as you see below, some of it is stubbed out for you. You will need to enter the name of your ADO.NET Entity Model as well as configure the access for the Data you want

   1: //------------------------------------------------------------------------------

   2: // <copyright file="WebDataService.svc.cs" company="Microsoft">

   3: //     Copyright (c) Microsoft Corporation.  All rights reserved.

   4: // </copyright>

   5: //------------------------------------------------------------------------------

   6: using System;

   7: using System.Collections.Generic;

   8: using System.Data.Services;

   9: using System.Data.Services.Common;

  10: using System.Linq;

  11: using System.ServiceModel.Web;

  12: using System.Web;


  14: namespace CPDemoAzureEFBCSEg

  15: {

  16:     public class NWindCustomers : DataService< /* TODO: put your data source class name here */ >

  17:     {

  18:         // This method is called only once to initialize service-wide policies.

  19:         public static void InitializeService(DataServiceConfiguration config)

  20:         {

  21:             // TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc.

  22:             // Examples:

  23:             // config.SetEntitySetAccessRule("MyEntityset", EntitySetRights.AllRead);

  24:             // config.SetServiceOperationAccessRule("MyServiceOperation", ServiceOperationRights.All);

  25:             config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;

  26:         }

  27:     }

  28: }

As this is Demoware, I am going to use an (*) for the configuration and tell it to do “ALL” but you can be more discrete.

   1: namespace CPDemoAzureEFBCSEg

   2: {

   3:     public class NWindCustomers : DataService<FabianNorthwindEntities>

   4:     {

   5:         // This method is called only once to initialize service-wide policies.

   6:         public static void InitializeService(DataServiceConfiguration config)

   7:         {

   8:             // TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc.

   9:             // Examples:

  10:             config.SetEntitySetAccessRule("*", EntitySetRights.All);

  11:             config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);

  12:             config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;

  13:         }

  14:     }

  15: }

Once you have done that you can preview the .SVC file in a browser and you should see what i have below


by typing in Customers in the URI, you will get an OData result set coming back to you. Pay attention to this URI you will need it for your next project.


Create a SharePoint App Project for your ECT

Ok, add a new project to your solution as i have below.


We are targeting a SPO tenant but this can be anywhere really. This is also a SharePoint Hosted App


Follow through on the wizard till your project is added.


Its really easy from here on in. You add a Content Type for an External Type to the new project


You provide the URI we have from the first project.


You select your Table, and leave the “check mark” for creating the List Instance so you will get your External Content Type and External List.


One you are done you will have an ECT and an EL as below in your project


If you open up your External Content Type you can see what I have below. At this point  you can

  • deploy it via visual studio
  • give it to someone to upload to a farm
  • deploy it manually yourself

here is the ECT below

   1: <?xml version="1.0" encoding="utf-16"?>

   2: <Model xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Name="FabianNorthwindModel" xmlns="http://schemas.microsoft.com/windows/2007/BusinessDataCatalog">

   3:   <LobSystems>

   4:     <LobSystem Name="CustDataFromAzure" Type="OData">

   5:       <Properties>

   6:         <Property Name="ODataServiceMetadataUrl" Type="System.String">http://localhost:50007/NWindCustomers.svc/$metadata</Property>

   7:         <Property Name="ODataServiceMetadataAuthenticationMode" Type="System.String">PassThrough</Property>

   8:         <Property Name="ODataServicesVersion" Type="System.String">2.0</Property>

   9:       </Properties>

  10:       <AccessControlList>

  11:         <AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">

  12:           <Right BdcRight="Edit" />

  13:           <Right BdcRight="Execute" />

  14:           <Right BdcRight="SelectableInClients" />

  15:           <Right BdcRight="SetPermissions" />

  16:         </AccessControlEntry>

  17:       </AccessControlList>

  18:       <LobSystemInstances>

  19:         <LobSystemInstance Name="CustDataFromAzure">

  20:           <Properties>

  21:             <Property Name="ODataServiceUrl" Type="System.String">http://localhost:50007/NWindCustomers.svc</Property>

  22:             <Property Name="ODataServiceAuthenticationMode" Type="System.String">PassThrough</Property>

  23:             <Property Name="ODataFormat" Type="System.String">application/atom+xml</Property>

  24:             <Property Name="HttpHeaderSetAcceptLanguage" Type="System.Boolean">true</Property>

  25:           </Properties>

  26:         </LobSystemInstance>

  27:       </LobSystemInstances>

  28:       <Entities>

  29:         <Entity Name="Customers" DefaultDisplayName="Customers" Namespace="FabianNorthwindModel" Version="" EstimatedInstanceCount="2000">

  30:           <Properties>

  31:             <Property Name="ExcludeFromOfflineClientForList" Type="System.String">False</Property>

  32:           </Properties>

  33:           <AccessControlList>

  34:             <AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">

  35:               <Right BdcRight="Edit" />

  36:               <Right BdcRight="Execute" />

  37:               <Right BdcRight="SelectableInClients" />

  38:               <Right BdcRight="SetPermissions" />

  39:             </AccessControlEntry>

  40:           </AccessControlList>

  41:           <Identifiers>

  42:             <Identifier Name="CustomerID" TypeName="System.String" />

  43:           </Identifiers>

  44:           <Methods>

  45:             <Method Name="CreateCustomer" DefaultDisplayName="Create Customer" IsStatic="false">

  46:               <Properties>

  47:                 <Property Name="ODataEntityUrl" Type="System.String">/Customers</Property>

  48:               </Properties>

  49:               <AccessControlList>

  50:                 <AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">

  51:                   <Right BdcRight="Edit" />

  52:                   <Right BdcRight="Execute" />

  53:                   <Right BdcRight="SelectableInClients" />

  54:                   <Right BdcRight="SetPermissions" />

  55:                 </AccessControlEntry>

  56:               </AccessControlList>

  57:               <Parameters>

  58:                 <Parameter Name="@CustomerID" Direction="In">

  59:                   <TypeDescriptor Name="CustomerID" DefaultDisplayName="CustomerID" TypeName="System.String" IdentifierName="CustomerID" CreatorField="true" />

  60:                 </Parameter>

  61:                 <Parameter Name="@CompanyName" Direction="In">

  62:                   <TypeDescriptor Name="CompanyName" DefaultDisplayName="CompanyName" TypeName="System.String" CreatorField="true" />

  63:                 </Parameter>

  64:                 <Parameter Name="@ContactName" Direction="In">

  65:                   <TypeDescriptor Name="ContactName" DefaultDisplayName="ContactName" TypeName="System.String" CreatorField="true" />

  66:                 </Parameter>

  67:                 <Parameter Name="@ContactTitle" Direction="In">

  68:                   <TypeDescriptor Name="ContactTitle" DefaultDisplayName="ContactTitle" TypeName="System.String" CreatorField="true" />

  69:                 </Parameter>

  70:                 <Parameter Name="@Address" Direction="In">

  71:                   <TypeDescriptor Name="Address" DefaultDisplayName="Address" TypeName="System.String" CreatorField="true" />

  72:                 </Parameter>

  73:                 <Parameter Name="@City" Direction="In">

  74:                   <TypeDescriptor Name="City" DefaultDisplayName="City" TypeName="System.String" CreatorField="true" />

  75:                 </Parameter>

  76:                 <Parameter Name="@Region" Direction="In">

  77:                   <TypeDescriptor Name="Region" DefaultDisplayName="Region" TypeName="System.String" CreatorField="true" />

  78:                 </Parameter>

  79:                 <Parameter Name="@PostalCode" Direction="In">

  80:                   <TypeDescriptor Name="PostalCode" DefaultDisplayName="PostalCode" TypeName="System.String" CreatorField="true" />

  81:                 </Parameter>

  82:                 <Parameter Name="@Country" Direction="In">

  83:                   <TypeDescriptor Name="Country" DefaultDisplayName="Country" TypeName="System.String" CreatorField="true" />

  84:                 </Parameter>

  85:                 <Parameter Name="@Phone" Direction="In">

  86:                   <TypeDescriptor Name="Phone" DefaultDisplayName="Phone" TypeName="System.String" CreatorField="true" />

  87:                 </Parameter>

  88:                 <Parameter Name="@Fax" Direction="In">

  89:                   <TypeDescriptor Name="Fax" DefaultDisplayName="Fax" TypeName="System.String" CreatorField="true" />

  90:                 </Parameter>

  91:                 <Parameter Name="@CreateCustomer" Direction="Return">

  92:                   <TypeDescriptor Name="CreateCustomer" DefaultDisplayName="CreateCustomer" TypeName="Microsoft.BusinessData.Runtime.DynamicType">

  93:                     <TypeDescriptors>

  94:                       <TypeDescriptor Name="CustomerID" DefaultDisplayName="CustomerID" TypeName="System.String" IdentifierName="CustomerID" ReadOnly="true" />

  95:                       <TypeDescriptor Name="CompanyName" DefaultDisplayName="CompanyName" TypeName="System.String" />

  96:                       <TypeDescriptor Name="ContactName" DefaultDisplayName="ContactName" TypeName="System.String" />

  97:                       <TypeDescriptor Name="ContactTitle" DefaultDisplayName="ContactTitle" TypeName="System.String" />

  98:                       <TypeDescriptor Name="Address" DefaultDisplayName="Address" TypeName="System.String" />

  99:                       <TypeDescriptor Name="City" DefaultDisplayName="City" TypeName="System.String" />

 100:                       <TypeDescriptor Name="Region" DefaultDisplayName="Region" TypeName="System.String" />

 101:                       <TypeDescriptor Name="PostalCode" DefaultDisplayName="PostalCode" TypeName="System.String" />

 102:                       <TypeDescriptor Name="Country" DefaultDisplayName="Country" TypeName="System.String" />

 103:                       <TypeDescriptor Name="Phone" DefaultDisplayName="Phone" TypeName="System.String" />

 104:                       <TypeDescriptor Name="Fax" DefaultDisplayName="Fax" TypeName="System.String" />

 105:                     </TypeDescriptors>

 106:                   </TypeDescriptor>

 107:                 </Parameter>

 108:               </Parameters>

 109:               <MethodInstances>

 110:                 <MethodInstance Name="CreateCustomer" Type="Creator" ReturnParameterName="@CreateCustomer" ReturnTypeDescriptorPath="CreateCustomer">

 111:                   <AccessControlList>

 112:                     <AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">

 113:                       <Right BdcRight="Edit" />

 114:                       <Right BdcRight="Execute" />

 115:                       <Right BdcRight="SelectableInClients" />

 116:                       <Right BdcRight="SetPermissions" />

 117:                     </AccessControlEntry>

 118:                   </AccessControlList>

 119:                 </MethodInstance>

 120:               </MethodInstances>

 121:             </Method>

 122:             <Method Name="ReadSpecificCustomer" DefaultDisplayName="Read Specific Customer" IsStatic="false">

 123:               <Properties>

 124:                 <Property Name="ODataEntityUrl" Type="System.String">/Customers(CustomerID='@CustomerID')</Property>

 125:               </Properties>

 126:               <AccessControlList>

 127:                 <AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">

 128:                   <Right BdcRight="Edit" />

 129:                   <Right BdcRight="Execute" />

 130:                   <Right BdcRight="SelectableInClients" />

 131:                   <Right BdcRight="SetPermissions" />

 132:                 </AccessControlEntry>

 133:               </AccessControlList>

 134:               <Parameters>

 135:                 <Parameter Name="@CustomerID" Direction="In">

 136:                   <TypeDescriptor Name="CustomerID" DefaultDisplayName="CustomerID" TypeName="System.String" IdentifierName="CustomerID" />

 137:                 </Parameter>

 138:                 <Parameter Name="@Customer" Direction="Return">

 139:                   <TypeDescriptor Name="Customer" DefaultDisplayName="Customer" TypeName="Microsoft.BusinessData.Runtime.DynamicType">

 140:                     <TypeDescriptors>

 141:                       <TypeDescriptor Name="CustomerID" DefaultDisplayName="CustomerID" TypeName="System.String" IdentifierName="CustomerID" ReadOnly="true" />

 142:                       <TypeDescriptor Name="CompanyName" DefaultDisplayName="CompanyName" TypeName="System.String">

 143:                         <Properties>

 144:                           <Property Name="RequiredInForms" Type="System.Boolean">true</Property>

 145:                         </Properties>

 146:                       </TypeDescriptor>

 147:                       <TypeDescriptor Name="ContactName" DefaultDisplayName="ContactName" TypeName="System.String" />

 148:                       <TypeDescriptor Name="ContactTitle" DefaultDisplayName="ContactTitle" TypeName="System.String" />

 149:                       <TypeDescriptor Name="Address" DefaultDisplayName="Address" TypeName="System.String" />

 150:                       <TypeDescriptor Name="City" DefaultDisplayName="City" TypeName="System.String" />

 151:                       <TypeDescriptor Name="Region" DefaultDisplayName="Region" TypeName="System.String" />

 152:                       <TypeDescriptor Name="PostalCode" DefaultDisplayName="PostalCode" TypeName="System.String" />

 153:                       <TypeDescriptor Name="Country" DefaultDisplayName="Country" TypeName="System.String" />

 154:                       <TypeDescriptor Name="Phone" DefaultDisplayName="Phone" TypeName="System.String" />

 155:                       <TypeDescriptor Name="Fax" DefaultDisplayName="Fax" TypeName="System.String" />

 156:                     </TypeDescriptors>

 157:                   </TypeDescriptor>

 158:                 </Parameter>

 159:               </Parameters>

 160:               <MethodInstances>

 161:                 <MethodInstance Name="ReadSpecificCustomer" Type="SpecificFinder" Default="true" ReturnParameterName="@Customer" ReturnTypeDescriptorPath="Customer">

 162:                   <AccessControlList>

 163:                     <AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">

 164:                       <Right BdcRight="Edit" />

 165:                       <Right BdcRight="Execute" />

 166:                       <Right BdcRight="SelectableInClients" />

 167:                       <Right BdcRight="SetPermissions" />

 168:                     </AccessControlEntry>

 169:                   </AccessControlList>

 170:                 </MethodInstance>

 171:               </MethodInstances>

 172:             </Method>

 173:             <Method Name="ReadAllCustomer" DefaultDisplayName="Read All Customer" IsStatic="false">

 174:               <Properties>

 175:                 <Property Name="ODataEntityUrl" Type="System.String">/Customers?$top=@LimitCustomerss</Property>

 176:               </Properties>

 177:               <AccessControlList>

 178:                 <AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">

 179:                   <Right BdcRight="Edit" />

 180:                   <Right BdcRight="Execute" />

 181:                   <Right BdcRight="SelectableInClients" />

 182:                   <Right BdcRight="SetPermissions" />

 183:                 </AccessControlEntry>

 184:               </AccessControlList>

 185:               <FilterDescriptors>

 186:                 <FilterDescriptor Name="LimitFilter" DefaultDisplayName="LimitFilter" Type="Limit" />

 187:               </FilterDescriptors>

 188:               <Parameters>

 189:                 <Parameter Name="@LimitCustomerss" Direction="In">

 190:                   <TypeDescriptor Name="LimitCustomerss" DefaultDisplayName="LimitCustomerss" TypeName="System.Int32" AssociatedFilter="LimitFilter">

 191:                     <Properties>

 192:                       <Property Name="LogicalOperatorWithPrevious" Type="System.String">None</Property>

 193:                       <Property Name="Order" Type="System.String">0</Property>

 194:                     </Properties>

 195:                     <DefaultValues>

 196:                       <DefaultValue MethodInstanceName="ReadAllCustomer" Type="System.Int32">100</DefaultValue>

 197:                     </DefaultValues>

 198:                   </TypeDescriptor>

 199:                 </Parameter>

 200:                 <Parameter Name="@Customers" Direction="Return">

 201:                   <TypeDescriptor Name="Customers" DefaultDisplayName="Customers" TypeName="Microsoft.BusinessData.Runtime.IDynamicTypeEnumerator" IsCollection="true">

 202:                     <TypeDescriptors>

 203:                       <TypeDescriptor Name="Customer" DefaultDisplayName="Customer" TypeName="Microsoft.BusinessData.Runtime.DynamicType">

 204:                         <TypeDescriptors>

 205:                           <TypeDescriptor Name="CustomerID" DefaultDisplayName="CustomerID" TypeName="System.String" IdentifierName="CustomerID" ReadOnly="true" />

 206:                           <TypeDescriptor Name="CompanyName" DefaultDisplayName="CompanyName" TypeName="System.String">

 207:                             <Properties>

 208:                               <Property Name="RequiredInForms" Type="System.Boolean">true</Property>

 209:                             </Properties>

 210:                           </TypeDescriptor>

 211:                           <TypeDescriptor Name="ContactName" DefaultDisplayName="ContactName" TypeName="System.String" />

 212:                           <TypeDescriptor Name="ContactTitle" DefaultDisplayName="ContactTitle" TypeName="System.String" />

 213:                           <TypeDescriptor Name="Address" DefaultDisplayName="Address" TypeName="System.String" />

 214:                           <TypeDescriptor Name="City" DefaultDisplayName="City" TypeName="System.String" />

 215:                           <TypeDescriptor Name="Region" DefaultDisplayName="Region" TypeName="System.String" />

 216:                           <TypeDescriptor Name="PostalCode" DefaultDisplayName="PostalCode" TypeName="System.String" />

 217:                           <TypeDescriptor Name="Country" DefaultDisplayName="Country" TypeName="System.String" />

 218:                           <TypeDescriptor Name="Phone" DefaultDisplayName="Phone" TypeName="System.String" />

 219:                           <TypeDescriptor Name="Fax" DefaultDisplayName="Fax" TypeName="System.String" />

 220:                         </TypeDescriptors>

 221:                       </TypeDescriptor>

 222:                     </TypeDescriptors>

 223:                   </TypeDescriptor>

 224:                 </Parameter>

 225:               </Parameters>

 226:               <MethodInstances>

 227:                 <MethodInstance Name="ReadAllCustomer" Type="Finder" Default="true" ReturnParameterName="@Customers" ReturnTypeDescriptorPath="Customers">

 228:                   <AccessControlList>

 229:                     <AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">

 230:                       <Right BdcRight="Edit" />

 231:                       <Right BdcRight="Execute" />

 232:                       <Right BdcRight="SelectableInClients" />

 233:                       <Right BdcRight="SetPermissions" />

 234:                     </AccessControlEntry>

 235:                   </AccessControlList>

 236:                 </MethodInstance>

 237:               </MethodInstances>

 238:             </Method>

 239:             <Method Name="UpdateCustomer" DefaultDisplayName="Update Customer" IsStatic="false">

 240:               <Properties>

 241:                 <Property Name="ODataEntityUrl" Type="System.String">/Customers(CustomerID='@CustomerID')</Property>

 242:               </Properties>

 243:               <AccessControlList>

 244:                 <AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">

 245:                   <Right BdcRight="Edit" />

 246:                   <Right BdcRight="Execute" />

 247:                   <Right BdcRight="SelectableInClients" />

 248:                   <Right BdcRight="SetPermissions" />

 249:                 </AccessControlEntry>

 250:               </AccessControlList>

 251:               <Parameters>

 252:                 <Parameter Name="@CustomerID" Direction="In">

 253:                   <TypeDescriptor Name="CustomerID" DefaultDisplayName="CustomerID" TypeName="System.String" IdentifierName="CustomerID" UpdaterField="true" />

 254:                 </Parameter>

 255:                 <Parameter Name="@CompanyName" Direction="In">

 256:                   <TypeDescriptor Name="CompanyName" DefaultDisplayName="CompanyName" TypeName="System.String" UpdaterField="true" />

 257:                 </Parameter>

 258:                 <Parameter Name="@ContactName" Direction="In">

 259:                   <TypeDescriptor Name="ContactName" DefaultDisplayName="ContactName" TypeName="System.String" UpdaterField="true" />

 260:                 </Parameter>

 261:                 <Parameter Name="@ContactTitle" Direction="In">

 262:                   <TypeDescriptor Name="ContactTitle" DefaultDisplayName="ContactTitle" TypeName="System.String" UpdaterField="true" />

 263:                 </Parameter>

 264:                 <Parameter Name="@Address" Direction="In">

 265:                   <TypeDescriptor Name="Address" DefaultDisplayName="Address" TypeName="System.String" UpdaterField="true" />

 266:                 </Parameter>

 267:                 <Parameter Name="@City" Direction="In">

 268:                   <TypeDescriptor Name="City" DefaultDisplayName="City" TypeName="System.String" UpdaterField="true" />

 269:                 </Parameter>

 270:                 <Parameter Name="@Region" Direction="In">

 271:                   <TypeDescriptor Name="Region" DefaultDisplayName="Region" TypeName="System.String" UpdaterField="true" />

 272:                 </Parameter>

 273:                 <Parameter Name="@PostalCode" Direction="In">

 274:                   <TypeDescriptor Name="PostalCode" DefaultDisplayName="PostalCode" TypeName="System.String" UpdaterField="true" />

 275:                 </Parameter>

 276:                 <Parameter Name="@Country" Direction="In">

 277:                   <TypeDescriptor Name="Country" DefaultDisplayName="Country" TypeName="System.String" UpdaterField="true" />

 278:                 </Parameter>

 279:                 <Parameter Name="@Phone" Direction="In">

 280:                   <TypeDescriptor Name="Phone" DefaultDisplayName="Phone" TypeName="System.String" UpdaterField="true" />

 281:                 </Parameter>

 282:                 <Parameter Name="@Fax" Direction="In">

 283:                   <TypeDescriptor Name="Fax" DefaultDisplayName="Fax" TypeName="System.String" UpdaterField="true" />

 284:                 </Parameter>

 285:               </Parameters>

 286:               <MethodInstances>

 287:                 <MethodInstance Name="UpdateCustomer" Type="Updater">

 288:                   <AccessControlList>

 289:                     <AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">

 290:                       <Right BdcRight="Edit" />

 291:                       <Right BdcRight="Execute" />

 292:                       <Right BdcRight="SelectableInClients" />

 293:                       <Right BdcRight="SetPermissions" />

 294:                     </AccessControlEntry>

 295:                   </AccessControlList>

 296:                 </MethodInstance>

 297:               </MethodInstances>

 298:             </Method>

 299:             <Method Name="DeleteCustomer" DefaultDisplayName="Delete Customer" IsStatic="false">

 300:               <Properties>

 301:                 <Property Name="ODataEntityUrl" Type="System.String">/Customers(CustomerID='@CustomerID')</Property>

 302:               </Properties>

 303:               <AccessControlList>

 304:                 <AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">

 305:                   <Right BdcRight="Edit" />

 306:                   <Right BdcRight="Execute" />

 307:                   <Right BdcRight="SelectableInClients" />

 308:                   <Right BdcRight="SetPermissions" />

 309:                 </AccessControlEntry>

 310:               </AccessControlList>

 311:               <Parameters>

 312:                 <Parameter Name="@CustomerID" Direction="In">

 313:                   <TypeDescriptor Name="CustomerID" DefaultDisplayName="CustomerID" TypeName="System.String" IdentifierName="CustomerID" />

 314:                 </Parameter>

 315:               </Parameters>

 316:               <MethodInstances>

 317:                 <MethodInstance Name="DeleteCustomer" Type="Deleter">

 318:                   <AccessControlList>

 319:                     <AccessControlEntry Principal="STS|SecurityTokenService|http://sharepoint.microsoft.com/claims/2009/08/isauthenticated|true|http://www.w3.org/2001/XMLSchema#string">

 320:                       <Right BdcRight="Edit" />

 321:                       <Right BdcRight="Execute" />

 322:                       <Right BdcRight="SelectableInClients" />

 323:                       <Right BdcRight="SetPermissions" />

 324:                     </AccessControlEntry>

 325:                   </AccessControlList>

 326:                 </MethodInstance>

 327:               </MethodInstances>

 328:             </Method>

 329:           </Methods>

 330:         </Entity>

 331:       </Entities>

 332:     </LobSystem>

 333:   </LobSystems>

 334: </Model>

Finally your project will look as i have below and you are done



I hope this is helpful, it was rather rushed, but i promised it in a few hours turnaround.

December 13, 2013 Posted by | Azure, Business Connectivity Services, Entity Framework, OData, Office 365, REST, SharePoint 2013, SharePoint How-To, Visual Studio 2013, WCF, Windows Azure | 1 Comment

Not SharePoint but cool anyway MVC5 EF6 and Azure


This post is about using Model View Controller (MVC) 5 in Visual Studio 2013 with Entity Framework 6 to do CRUD operations on a SQL Azure Database.  It is definitely NOT Rocket Science but there are a few GOTCHAS to look out for and definitely a new way of doing business with MVC 5 as it relates to Controllers and Scaffolding with Entity Framework.

My code will be up at Code.MSDN.com and I will put it in Git Hub as well. I will update the post with the links when i upload them.

Create your Project

The first thing you have to do is create your project. So, Launch VS 2013 as Administrator and under the Installed Templates click Web and select the “ASP.NET Web Application”, provide a meaningful name and click OK.


The next thing we will do is select MVC since that is what we are doing here today. As this is DEMOware we will not be doing any Unit Testing as well so unselect that if it is selected for you.



Once complete your project will look as mine does below.



and a project ReadMe that invites you to customize the Applications etc. will be there for you as well.

Create your Model

Since we are connecting to a Data Source, as in our case it is my Northwind Customers Table in SQL Azure, what we need to do is create an Object (Class) that represents that schema, so take a look at your Columns and lets add a Class file next


Above is the Silverlight App that ships with SQL Azure Management and you can see some of the fields we will Model. To Model the entity, you add a new Class to your Project as i have below. Right click on the Model Folder and..


Inside that Class go ahead and create the necessary auto generated properties as you can see in the code snippet below


  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Web;
  6. namespace AzureNorthWindCustMVC5Demo.Models
  7. {
  8.     public class Customer
  9.     {
  10.         public string CustomerID { get; set; }
  11.         public string CompanyName { get; set; }
  12.         public string ContactName { get; set; }
  13.         public string ContactTitle { get; set; }
  14.         public string Address { get; set; }
  15.         public string City { get; set; }
  16.         public string Region { get; set; }
  17.         public string PostalCode { get; set; }
  18.         public string Country { get; set; }
  19.         public string Phone { get; set; }
  20.         public string Fax { get; set; }
  21.     }
  22. }

With that, you have your Model. This is a good time to Build your project so the Model will be available for the Controller which we will do next.

Create your Scaffolding and Controller

This is one place where the cool new features of MVC 5 kicks in, you can Right Click on your Controller Folder and add “New Scaffolded Item”. What does for you is literally ALL THE WORK necessary to have full CRUD capabilities back to your Data Store. It will

  • Create your Context Class for your Database
  • Create your Connection String in the Web.Config [which you will need to Modify anyway because by default it points local]
  • Create an instance of the Context Class in your Controller so you can interact with the Database
  • Create all the Views for you to
    • See a List of All items returned
    • See Single Item
    • See Detailed Items
    • Edit Items
    • Delete Items
    • Create a New Item

Here is how you do it, right click on the Controller Folder in your Project and do Add, New Scaffolded Item…


You have the option to do this manually by doing and Empty Controller but since this example is about Entity Framework 6, we will use a controller that will create all views with EF6.


Once that is done, you can wire up the Data Connection for the Model and the Data Context. Assuming that you Build your project as i said earlier, you should see as i do a Model Class with the name you need. In my case “Customer”


Once you have selected that you can now do “New Data Context” for it to create that Class for you as well. I named mine to be reflective of the Table i am working with. See below…



One minor change that I did. You will notice above my Controller Name “WAS” Home… but I realized that there was one already created called Home so i changed it to Customer as you can see below.



Once you click Add, you should see your project grow in leaps and bounds like mine below




Now you may think your work is done but there are at least Two (2) more things needed to make this connect to your Azure Database. The first thing is to (1) Modify or ADD the connection string to your SQL Azure Database to the Web.Config in the root of your Project. If you dont MVC will create a NEW database for you locally in SQL Express more than likely if the Controller DOES NOT find a Connection String of its Name inside the Web.Config. That is why you will see below that the Name of MY connections string is the same name of my Context Class.


Below is a code snippet of the connection string minus my credentials.

  1. <entityFramework>
  2.   <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
  3.   <providers>
  4.     <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
  5.   </providers>
  6. </entityFramework>
  7. <connectionStrings>
  8.   <add name="CustomerContext" connectionString="Server=tcp:uboxhere.database.windows.net,1433;Database=FabianNorthwind;User ID=UrUserNameHere;Password=P@ssword123;Trusted_Connection=False;Encrypt=True;Connection Timeout=30" providerName="System.Data.SqlClient" />
  9. </connectionStrings>
  10. </configuration>


The second thing (number 2) is to Add a command to the Global.asax file which is fired upon App Launch to Initialize the Database connection I want in Azure, you will need to have a reference to the System.Data.Entity namespace as i have shown below when you do this. You will notice it is also bound to the Model Context Class.


Just a little weird thing that I noticed.  I did this on my Windows 8.1 box and when I tried to launch the browser to test my work, IIS Express failed with some Process number, so i changed my Build to point to my Local IIS and created a Virtual Directory as you see below.


Once I did that, when I clicked F5 to test this out, it worked as expected. The circle is complete 🙂




This is really cool, i know I usually talk about SharePoint but this is equally important and you will also see a new MVC Template in SharePoint for Visual Studio 2013 in Cloud Apps, make sure you give that a try. Chaks has a good post out on it here.

My code will be up at Code.MSDN.com and I will put it in Git Hub as well. I will update the post with the links when i upload them.

For now Enjoy.. c u l8r

November 6, 2013 Posted by | Azure, Entity Framework, MVC, Visual Studio 2013 | , , , | 2 Comments

Why it pays to have Smart Friends to Encourage you

Why write this blog post?

Sure its late and YES I could be rotting my brain away on the Idiot Box, but what started off as a Taunt by Ram turned out to consume my life for 2 days straight but with useful results, challenges that were overcome, and a better appreciation for not just Cloud, but the integration of Cloud and On-Prem using Windows Azure.  Let me tell you what I did, and how easy it was… in the end, plus the real implications of it.

First a little history – Pre Taunt

So, as I prepare for my sessions at #SPLive in Orlando in 3 weeks, I wanted to knock out a few Demos and make sure that I could showcase just about anything anyone asked of me based on the Session Abstract/Topic. In furtherance of that, I decided to do the following, build out solutions employing

SharePoint Designer 2013

  • External Content Type using a Native SQL Data Connection
  • External Content Type using an On-Prem (i.e. Hosted on one of my Dev Rig VMs) Windows Communications Foundation [WCF] Data Connection – JSON enabled
  • External Content Type using a .NET Assembly (built on my Visual Studio 2012, Deployed as a Farm Solution to my On-Prem SP2013) Data Connection
  • Workflow using the same On-Prem WCF above in my On-Prem Farm

Visual Studio 2012

  • A Locally IIS hosted WCF Service Library that exposes Northwind data from a Local SQL Server 2012 Box
  • A Locally IIS hosted OData Service Endpoint that exposes Northwind data from a Local SQL Server 2012 Box
  • External Content Type built as a .NET Assembly to be deployed to my ON-Prem SharePoint 2013 Farm
  • External Content Type AND External List SharePoint 2013 App built as an OData Sourced Application deployed to my ON-Prem SharePoint 2013 Farm

For every Instance of the WCF and the App Model External Content Type, I also targeted my Office 365 Tennant to surface the Data as well. I was pretty satisfied with myself until my good friend sent this tweet, and I know it was in jest…


but… I took it as a challenge and, I rarely back down from a challenge 🙂 so, since I have a MSDN subscription, there was “really” nothing holding me back besides my inexperience creating Azure Web Roles, which is what you need to do in order to have the requisite Data Access Points (URI) to create External Content Types and potentially Workflows. 

What Next you say…

So, with a little research on Google scratch that, I mean Bing, I found a few MSDN, and TechNet blogs on how to create Web Roles, although not many of them “accurately” showed you how to use Visual Studio to DEPLOY your solution back to Azure. Anyway, it was surprisingly easy, although initially it was somewhat intimidating and i did get snagged on a GOTCHA which i will blog about later when doing a ASP.NET Web Role where it requires you to lower your version of the System.Data.Client assembly from 5.0 to 4.something in order for it work in Azure, i say that because it worked perfectly when I debugged it locally on my Visual Studio IIS. I also had to create an Azure SQL Instance and used a script I downloaded from CodePlex to restore a Northwind Database to my Azure SQL Instance and then I set up firewall rules to allow me to access it over the internet.

But with quick turn around and because i could just Refactor my original On-Prem code logic, I was able to create the following

Visual Studio 2012

  • Azure ASP.NET Web Role that published as a Cloud Service which used OData via ADO.NET Entity Framework to get a Cloud based URI that i can do CRUD operations on
  • Azure WCF Web Role that published as a Cloud Service which used WCF via ADO.NET Entity Framework to get a Cloud based URI that i can do CRUD operations on as well


Now I can really Mix and Match, I can

  1. Use Azure (Cloud) Hosted Data via an ON-Prem WCF or OData End Point and surface that information both on my ON-Prem SharePoint or my Office 365 Instance
  2. Use Azure (Cloud) Hosted Data via an Azure Cloud Service WCF or OData End Point and surface that information both on my ON-Prem SharePoint or my Office 365 Instance
  3. Plus everything I had when I started off

The takeaway here is that with very little investments in time and effort I extended my solution to a “MODERN” approach. I had Cloud in the sentence 🙂


Other Positive Implications

So, what made this so easy for me was I signed up for TFS Online here http://tfs.visualstudio.com/en-us/tfs-welcome.aspx and EVEN WITHOUT a MSDN Subscription you can sign up for FREE and get 5 accounts in one instance.


What I think is GOLD is…

  • You have a place to store all your CODE/ Work and before you ask, it supports different formats (see image below)
  • Your Code/Work is accessible from Anywhere you have an Internet Connection now
  • You can reliably share your Code/Work with anyone now, rather than Zipping it up and Email it
  • Need Help with some of you work… Invite people as smart or smarter than you to review our code, many hands make light load 🙂
  • Most beneficial of all is that you can configure Continual Integration. I know my good friend Jeremy Thake always talk about Application Lifecycle Management (ALM) and you can employ some of those techniques from Azure through TFS Online and your Visual Studio with multiple Team Member… and guess what… FOR FREE

So that’s all I have to say, I guess we really Paid It Forward RAM, you encouraged me to do this, I in turn, documented my efforts and hope that someone else can take it from here.


Cheers all, have a great night. Oh yeah, VS 2013 is out now. GO get it.

October 17, 2013 Posted by | Azure, JSON, OData, REST, SharePoint 2013, SharePoint 2013 Workflows, SharePoint Designer 2013, SharePoint Development, SQL Server, Visual Studio 2012, WCF | , , | Leave a comment

ACTUALLY RESOLVED: Unable to Create List using SharePoint 2013 REST API in SPD2013

Are you ready for this?

Im never satisfied with the answer “No you cant do that”, not as a Developer 🙂 So, i began to read through some TechNet and MSDN articles for Workflow and found this Gem. http://msdn.microsoft.com/en-us/library/jj822159.aspx 

What this Gem does is EXACTLY what Chris Givens found out and did in his PowerShell but as we discussed in my “Resolved post”, we cant run those scripts inside Office 365 SharePoint Online. So, it seems that you have to activate a Site Feature in your Site that you need this “elevated permission” then you need to copy the App Principal ID from the one you want elevated then take that to a “hidden” link inside the App Catalog Site http://{hostname}/{catalog site}/_layouts/15/appinv.aspx and then work your magic to elevate the permissions via an XML node copy / paste magic.

Anyway the GOOD NEWS is that I have tested this in SharePoint Online, and it works like a champ, see below for screenshots.

If you would like the full history of this, see the following post in chronology

  1. https://fabiangwilliams.wordpress.com/2013/09/06/help-unable-to-create-list-using-sharepoint-2013-rest-api-in-spd2013/
  2. https://fabiangwilliams.wordpress.com/2013/09/07/resolved-unable-to-create-list-using-sharepoint-2013-rest-api-in-spd2013/

Proving it out

First me activating the Feature


Next grabbing the App Principal ID needed for the Workflow in question. Now i purposely cut off all of the ID, i dont want some crafty person out there using it. Just realize that this is the same account that Chris and I talked about in the PowerShell


then moving the piece of Workflow logic that does the List Creation inside the App Step inside SharePoint Designer


and finally re-running the Workflow will yield the below in the Workflow History


and just to bring it home, here is the new List or (App i guess) Created



Cheers FGW

September 8, 2013 Posted by | Azure, JSON, Office 365, SharePoint 2013, SharePoint 2013 Workflows, SharePoint Designer 2013, SharePoint How-To, Strange Stuff | 13 Comments

RESOLVED: Unable to Create List using SharePoint 2013 REST API in SPD2013


Ill start this post out by saying that this is why i so LOVE the SharePoint Community. It is a true example of "many hands make light work”, first Jim Bob Howard @jbhoward one of my @PlanetTech work colleagues faced a problem, since it was a topic of interest to me, I decided to put some time into it as well. I was able to prove out most of the issues, but there was this last one (see blog post to what this is referring to in a link below) that just didnt make sense.  What do i do when that happens, well I’ve never been ashamed to reach out to my friends in the SharePoint Community so I blogged the issue, showed what we did so far, and without tagging anyone in the tweet we had folks from the UK joining in the conversation, folks from all Time Zones here in the United States chiming in as well. Late Friday night I emailed a copy of the Workflow to my good buddy @givenscj Chris Givens.  I really wasn’t surprised when even on a Saturday, Chris called me up on the phone, and we spent like 2 hours on a Screen Share looking at ULS logs, then he went off on his own, and within an hour, he came back with a solution. 

The original problem was posted on the forums here

My Plea for help on my blog which gives more details than the forum post allows is here. This post is basically closing the loop on the problem


Chris blogged his findings here, go look at it, but the main point ill just borrow from is blog…

“…The main issue of Fabian’s was that when he made the Web Service call he would pass a pre-created FedAuth token (yeah I told him he would have to figure out how to generate this in the future) which established a context for him.  This context was as his SharePoint admin account, but the actual running account (the "actor") was the Workflow service.  Of course the SP Admin account can do whatever it wants, but the workflow service cannot.  This workflow service account is NOT the account that the actual workflow manager backend window service is running under.”

Screen Shots form what Chris and I worked on

First we wanted to see what was happening ON Prem with this both from a Fiddler standpoint as well as SharePoint Designer 2013, here is what we saw. The offending item was the account it is running under MS.SP.EXT which is the App Principal for the Workflow from Workflow Manager. Further down you will see this inside the Content Database and the permission it is set to run under.


with a little more detail below


Below is a peek into the App Principal Table. This table as Chris describes is where the App Principal Accounts live, you can see that i have a few that are Titled as my Workflow Apps and one called just “Workflow” and it is that one if you look under “Name” has MS.SP.EXT 🙂


Now, lets go look at the permissions, now mind you, if you look at permission it is set to “5” right now for the ID 1, that was set to “3” before i ran the PowerShell that Chris has on his web site and i will put below for complexness.


Here is the PowerShell below

PS C:\Users\spadmin> $web = Get-SPWeb http://farm1sp13svr1
PS C:\Users\spadmin> $appworkflow = Get-SPAppPrincipal -site http://farm1sp13svr1 -nameidentifier 31ed5e6e-979b-redacted
PS C:\Users\spadmin> Set-SPAppPrincipalPermission -AppPrincipal $appworkflow -site $web -right fullcontrol -scope site
PS C:\Users\spadmin>

Once I did that, all we did next was re-Run the workflow, NO other changes, here was our result


and in All Site Contents





So, all is well in the world of SharePoint again. I hope Chris goes and puts his solution as the answer to the question in the @Office365 Forums so we can have a record out there as well. I hope this helps someone else that falls prey to this, I agree with Chris, this is the first time I have ever seen anyone blog or talk about this in a public setting.


Fabian Williams with contributions from Chris Givens


So, because i wanted this to work in Office 365 as well, we needed to find out if these PowerShell options are available there too. For completeness I loaded up the ISE and I have here all the options that you can do with the App Model for GETS and SETS, both for On Prem and OnLine, you can see that the Online version is very limited




and sad to say I could get EVERYTHING from ONLINE in one screenshot. 😦 sad panda


If you want to know more about Powershell for SharePoint Online regarding how to set it up in your environment, see Patrick @pcfromdc Currans blog post here.




September 7, 2013 Posted by | Azure, JSON, Office 365, REST, SharePoint 2013, SharePoint 2013 Workflows, SharePoint Designer 2013, SharePoint Error/Resolution, SharePoint How-To, SharePoint Online | 1 Comment

Windows Azure hosting Linux Ubuntu Server with LAMP


As I prepare to go to Microsoft TechEd North America 2013 this weekend in New Orleans to work staff duty for Microsoft in the Windows Azure Conference Area, and coupled with the fact that I am reviving my skills in Linux Apache MySQL PHP (LAMP) I am going to do a blog on how easy it is to stand up a Ubuntu Linux Server 12.4 as a windows Azure Virtual Machine with LAMP installed and configured.

How do you get started with Azure

So, there are a few ways

  • Use the Free Trial that is there
  • Get a Subscription Outright
  • As a Part of your MSDN/MVP/ other Microsoft Affiliation Program

In this blog we will be using it from the vantage  point of an MSDN Subscription so if your Subscription has less or more, that’s probably why. As discussed however you can get Azure by signing up for the free version at http://windowsazure.com


If you have an account already you can just Log In from here as well.

Now that you are Logged In

So, as you can see, I have two items provisioned (1) Storage and (2) A Virtual Machine

Lets take a look at Storage first

If you are looking for a place to


The storage represented there can be used for just about anything except RDMS, its just simple storage. For me it is where the Virtual Hard Disk are stored, later on I can put whatever kind of storage I want actually. Now, although Azure gives you a way to interact with it, I prefer to use the Neudesic Azure Explorer tool. See below you can see that it has my VHD’s for all the Virtual Machines I built and are using now. Notwithstanding that, you can also store Tables and Queues in addition to the Blog Storage used to keep the Virtual Hard Disks.


We can save the conversation for another day for exploring the other uses of storage, but just to showcase the tool above lets see how you can create a new Table Storage


and once provisioned in the tool it looks like


But we came here to learn about using Azure to install Ubuntu in Azure so, lets get cracking.  So from the bottom of the Azure Portal manager click New and lets set about creating a new Virtual Machine.


Once you click “Virtual Machine” the portal will fan out and you may elect to spin up your VM via the Quick Create which is easy but provides you with significantly less Configurable options as well as taking the most stringent of defaults (one being requiring you to SSH through a Certificate), so we will choose “From Gallery” as outlined below


Form the gallery we will ofcoourse be choosing the Ubuntu Server 12.04LTS but as you can see in the green call out, I could have used a previous Image Template that I have there. The point being that IF you OWN licenses to OS’s you can upload the image to Azure [via the Storage mechanism previously discussed] and they will appear in the template here.



Speaking of customization, well one of the things you can do in this Azure install is choose what Version Release of Ubuntu Linux you want, you achieve that by the selection below


The next set of decisions are very important ones that you will want to jot down somewhere, especially the UserName and Password one.  Now you will notice that the credentials section “defaults” to uploading a certificate to Azure to let it know the box that you will be Secure Shell-ing in from. What that is THE best way to do this because it (1) encrypts the traffic (2) is overall more secure, we will not be doing that in this demo. Im my other ones, yes I do that.


So, in my case I am electing to do the password option


The next decision is one where advance preparation will make your life a lot easier.  So, you recall how earlier we discussed that you can provision storage and use them at your own convenience.  Well here is a good candidate for one. So, if this was production, I would definitely in advance of this selection set up a strong HA disk set for my storage and point it to that guy, as you see me doing here to this simple disk set.


Your next option is availability set, now this is just a Rip and Replace install so, I am not bothering with one, but you an read up here in the image as to what it is and how it is used.


When you complete that step, you will see that a Virtual Machine is being provisioned for you as below. the count to my Virtual Machine is now 2 up from 1


and after a few seconds/minutes, as seen below you will have a brand new Virtual Machine up and running


Logging In for the First Time

So first thing first right, this is Ubuntu Linux, it is NOT Windows so, that means that you WILL NOT be RDP-ing into this box, although there are Linux packages for that as well. Your access will be via Secure Shell (SSH) to issue command via the command line, or you could install the Desktop untop of your server, but with my limited knowledge of Linux, I still would advise against that. There are plenty of tools out there for you if you want to exchange files FileZilla comes to mind, and ofcourse if you are on a Windows Desktop you can use Putty to SSH in.

As for me, I have a Ubuntu Desktop 12.04 VM that is on my Dev Rig Laptop, I can bring it up and RDP into it that then SSH into my Server with my Certificate that I have. Below, you will see a few things, (1) the Public IP address of this VM instance and in my Ubuntu Desktop you will see me establishing a SSH session for the very first time. You will notice that I am not going over Port 22 which is the standard SSH, that is because Azure masks that with a Public Port to thwart folks with nefarious intent.


Once you try to establish that session you will get the below warning, go ahead and accept, this is your box afterall.


And once that is done, you will be authenticated into your Azure Instance of your Ubuntu Linux server as seen below


What do we do Next

Well ideally what we would do next is see if there are any updates and upgrades to be done to the Install by issuing the following command, but as i said, this is a rip and replace

$ sudo apt-get install updates

then if there are any after it identifies them

$ sudo apt-get install upgrade

After that happens then its time to get the LAMP installation done.

Installing the “M” out of LAMP  – mySQL

So its time to install mySQL, as you can see below I am installing both the Server and the Client


I have the below screen shot only here once but as you install the “A” and the “P” out of Linux Apache MySQL PHP you will get this question again. So say “Yes” to them respectivly


For mySQL when you do the Install you will need to set the Root Password for it, go ahead and do so. You should jot this down again, because when we install phpMyAdmin, it is what we will be using to get into the Web Application.


Install Apache

Next is installing Apache, which is again, very straight forward…


Install PHP

Next you issue the command below to install PHP


Now after you install PHP, you will want to restart the Apache Service as you see below, and expect to see an “OK” coming back when it is done



Now that takes care of installing Ubuntu “L” then Apache “A” then mySQL “M” and then finally PHP “P” so there you go you have your LAMP server. Id also install or your favorite C compiler Im partial to installing build-essential

$ sudo apt-get install build-essential to get that going then you can crank out “C” and “C++” code on the box or you can put them in your CGI-BIN directory and call them from Apache

But for now, lets just make sure we can see the Apache Server from the Outside i.e. Public Internet. So to do that you will need open up a EndPoint AKA Port in Azure under your Virtual Machine, as you can see, so far its just the SSH port, but now we will add one for Port 80


Click Add EndPoint and then…


Name appropriately and Add it as seen below in the screen shot


Once you have done that you should be able to call up the URL from any browser and see the standard Welcome Page for an Apache Server as seen below


Well that does it for making sure that Apache is up and running but to test for PHP, you will need to create a simple script and copy it to the publishing folder where Apache reads from. Now ideally here again, I would move that folder from /var/www and put it soemwhere else, but for now we are using the default. In this example I am creating the file in my home directory using the VI editor, ofcourse you can use anyone you desire, some find “nano” or “pico” easy to use, even though VI has a steeper leaning curve, it is by far the most powerful IMO.


Below is the basic script everyone uses to prove out PHP running


Once you have done that then you need to copy this file to where Apache reads web pages from as previously discussed.


Once you have completed that copy, you can now call that page from any public browser and see the results as shown below.


One more piece of tool, I will install before calling it quits on this LAMP Server.

Install phpMyAdmin

So this is a great tool for managing mySQL, certainly more control can be gained by using the command line tools but this is more visual and is good IMO.  So issue the command below  to install it.


Once you do, this is another Web App available to anyone with rights and credentials.


Once you are in. The world is your oyster.


Clean Up

Now even though I get Azure with my MSDN subscription, I am not about to leave Servers I dont need running, and I have all but shown you all how to access my server from anywhere, so I am going to decommission it and delete it from Azure. Those steps are also very easy. First locate your Server from your list of VM’s and say Delete


Then Confirm the Delete. You can also delete the VHD as well that is in the Storage.


Below is the Azure Management Console telling me about the delete process


And now my virtual machines are now Down from 2 to 1



Azure is good, easy, great for Rip and Run scenarios, Proof of Concepts or Learning New stuff. Take it easy Irie.

May 26, 2013 Posted by | Azure, LAMP, Linux, Ubuntu, Windows Azure | Leave a comment