Fabian Williams SharePoint Blog

Solving problems with SharePoint day and night

SQL Azure to EF5 to OData to BCS EL

Précis

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

 

image

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

image

We will be targeting a Database called FabianNorthWind

image

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

image

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

image

Finally you will have your EF in your project

image

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.

image

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;

  13:  

  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

image

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.

image

Create a SharePoint App Project for your ECT

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

image

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

image

Follow through on the wizard till your project is added.

image

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

image

You provide the URI we have from the first project.

image

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.

image

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

image

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="1.0.0.0" 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

image

Summary

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

Advertisements

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

Windows Azure hosting Linux Ubuntu Server with LAMP

Précis

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

image

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

SNAGHTMLc06b4eb

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.

SNAGHTMLc0f693c

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

SNAGHTMLca2c7f2

and once provisioned in the tool it looks like

SNAGHTMLca35f02

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.

image

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

image

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.

 

SNAGHTMLd606e81

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

image

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.

image

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

image

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.

SNAGHTMLcc35053

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.

image

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

SNAGHTMLd6129a5

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

image

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.

image

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

image

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

image

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

image

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

image

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.

image

Install Apache

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

image

Install PHP

Next you issue the command below to install PHP

image

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

image

Testing

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

image

Click Add EndPoint and then…

image

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

SNAGHTMLd6202d3

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

image

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.

image

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

image

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

image

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

image

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.

image

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

image

Once you are in. The world is your oyster.

image

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

image

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

image

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

SNAGHTMLd63286d

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

SNAGHTMLd63dc60

Summary

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