Microsoft cloud engineer - SharePoint, Office 365, Azure, DotNet, Angular, JavaScript.
Microsoft cloud engineer - SharePoint, Office 365, Azure, DotNet, Angular, JavaScript.

App Model

SAAM – Site Asset App Model

Developers have more options in SharePoint 2013 than any version before.   App Model is center stage.  Understandably this has created some confusion and debate in the community.   I’d like to suggest another coding pattern to consider in addition to pure App Model which I call “Site Asset App Model.”

Long before SP2013 released, I would add jQuery “widgets” to pages in MOSS2007 and SP2010 with a Content Editor.  Upload HTML, CSS, and JS files.  Simple and effective.   Requires no special infrastructure changes.  This approach remains valid and has actually improved with advancements like :

  • JavaScript frameworks
  • Angular,  Knockout
  • HTML 5 browsers
  • REST /_api/ endpoints
  • ASP.Net WebAPI
  • Entity Framework
  • BreezeJS

I might not always use pure “App Model”, but I’m 100% sold on JavaScript front end development and the “from Bricks to Houses” philosophy (http://channel9.msdn.com/Events/SharePoint-Conference/2014/SPC404)    Call this whatever name you like, but JavaScript coding has advantages for both developers and administrators alike.    I suggest coding JS first, then fallback to C# wrapped in WebAPI over HTTP, and finally farm solution WSP as last resort.  

Please leave a comment if you found this helpful!  

shades_smile

Diagram

image
image

How to Use

Configure

  • Create new folder in Site Assets
  • Map drive letter
  • Create HTML/JS/CSS files with local IDE (Visual Studio, Brackets, NotePad++, etc.)
  • Add page to SharePoint site
  • Add Content Editor to page. Set source Property to HTML location.

Debug

  • Edit source HTML/JS/JSS
  • Reload with browser
  • Press F12 to debug, set breakpoints, inspect DOM
  • NOTE – adding the JS statement “debugger;” can help raise a local browser event. That can be a nice trick to more easily create breakpoints in your editor instead of scrolling the same codebase again with F12. http://www.w3schools.com/js/js_debugging.asp

Admittedly there are drawbacks:

  • No Visual Studio F5 debug
  • No full package (.APP)
  • No Office365 store
  • No app-only principal (limited to current user permissions)
  • Hard to deploy multiple instances

However, there might be times when SAAM is preferred:

  • Working on SP2007/2010
  • Lacking SP2013 App Model infrastructure (Wildcard DNS, Service Apps, etc.)
  • Visual Studio not available (required for .APP package/deploy)
  • Non-SharePoint developers comfortable editing HTML/JS/CSS directly

Comparison Table

FeatureSP2013
“App Model”
Site Assets
App Model
(SAAM)
HTTP call host web without SP Request Executor ProxyNOYES
Support REST to External Content Types made in SharePoint DesignerNOYES
List and Library user data kept if app uninstalled (code upgrade)NOYES
Create standard Views for lists and libraries with App user dataNOYES
Works on SP2007 and 2010 older versionsNOYES
Restricted to “App Web” where many features disabledYESNO
Requires server infrastructure changesYESNO
* Claims authenticationYESNO
* Wildcard DNS on networkYESNO
* Service ApplicationsYESNO
* Additional SQL databases and service accountsYESNO
Requires security manifestYESNO
* Permissions plan to useYESNO
* Web service endpoint URLsYESNO
Able to publish and sell in Office 365 StoreYESNO
Able to use App Identity Security PrincipalYESNO

SP2013 “App Model”

Site Assets App Model (SAAM)

straight-jacket-costume

References

http://channel9.msdn.com/Events/Speakers/Scot-Hillier

  • ​”From bricks to houses” > wider view beyond “App Model” looking at all front end coding (JS/REST)

http://www.itunity.com/community/questions/view/question/id/1

  • ​Use SharePoint where it makes sense (components ready), but now able to include a wider menu of 3rd party technology choices.  
  • Non-Microsoft, Google, others, and a whole web of innovation beyond SP core.

http://blogs.msdn.com/b/amigan/archive/2012/12/10/part-2-introduction-to-sharepoint-2013-app-model.aspx

  • Detailed comparison table
  • Yes, some things cannot be done in “App Model”
  • Yes, farm solutions are still valid  (but as a last resort – try front end coding first)

http://sharepointpromag.com/blog/sharepoint-2013-s-cloud-app-model-it-s-what-you-wanted-all-along

  • ​And ultimately, it’s going to be moot. In multi-tenant environments such as Office 365, this is the only real option.
  • Office365 is the gold standard for low administrative effort.

BreezeJS – Edit SQL table with < 100 lines of JS code [VIDEO]

With SharePoint 2013 and industry movement towards the cloud I’ve been exploring JavaScript as a primary way to develop rich applications.

One common challenge is data access.  

With C# I have years of experience with [System.Data] and can perform CRUD against SQL relational databases in my sleep.  Open connection, query, data adapter, fill DataTable, and voila!    Muscle memory. Second nature.  Tried and true methods.   However, in the new client side JS world I had no clue where to begin.

Enter Breeze.

 

People describe Breeze as “Entity Framework on the client in JavaScript” which sounds simple yet has profound implication for the developer.   CRUD operations, LINQ style query, navigating primary/foreign keys, input validation, caching, batch updates, and more.   That’s a lot to consider and new ideas take time to absorb.   Breeze could potentially replace:

  • ASP.Net (ASPX) web forms
  • ASCX user controls
  • InfoPath forms
  • SharePoint web parts
  • WCF 5.6 data services
  • OData
  • Classic WebAPI

 

I set out to code an example with a few goals:

  • Create simple SQL schema (two tables – parent/child – one to many)
  • Execute CRUD operations in JS against SQL  tables
  • Leverage JS plugins and NuGet “Install-Package” to load third party components
    • Install-Package breeze.webapi2.ef6
    • Install-Package breeze.angular
    • Install-Package angularjs.core
  • Little code as possible

The whole thing took less than 30 minutes and I edited video down to just 15.    I was impressed by how straightforward and easy the process was.   Breeze# in ASP.Net MVC for the back end WebAPI controller was nearly identical to the Breeze example code.   Add one C# method per entity (SQL table) and Breeze does the rest.  The JS front end took a little more time to understand but was also easy to apply.   Connect  Entity Manager to the Breeze URL and you’re ready for CRUD queries.    Amazing!     Given how easy Breeze is I would be hard pressed to use OData or manually created WebAPI controllers with C# code to query a database.   If you can use Breeze, then use it!    You’ll save lots of effort.

Please leave a comment if you found this helpful.   Thank you! 

shades_smile

 

Watch Video

[BreezeJS and WebAPI – Edit SQL table in JS with less than 100 lines of code]

 

Download Code

Download

http://spjeff.com/etc/Appraisal-Breeze-VS2013.zip

 

Screenshots

image
image

 

image

 

References

 

SharePoint 2013 – App Model 3 Tier Diagram

I needed a quick reference to introduce developers with the SharePoint 2013 App Model. 

For traditional ASP.Net and Dot Net coders there is a wide philosophy gap to cross when considering new applications written mostly in front-end JavaScript, HTML, and CSS.   Instead of coding “in” SharePoint (to augment the core product) we now code “next to” SharePoint (with additive REST/JSON endpoints).  

The stability which comes from this approach is significant.  We wan to run on-premise SharePoint similar to how Microsoft operates Office 365.   No more SharePoint customization lost during patching.   No more late night WSP and IISRESET outages.   Code can be modified more fluidly and IE breakpoints can even be set at a single user’s desktop when troubleshooting.   Exciting and powerful tools – which require a new way of thinking.

Please fee free to download the poster I made below.   Hope you find it helpful! 

shades_smile

 

12-27-2014 3-07-04 PM

WebAPI OData – 10 min video introduction (Visual Studio 2013)

I’ve been learning about OData and wanted to record a quick getting started video with how to create a new WebAPI project, add OData Controller, and send HTTP CRUD operations.  Below is an example using Adventure Works Departments with sample code, screenshots, and a 10 minute video introduction.   Please leave a comment if you found this helpful.  Thanks! 

shades_smile

Video Content

  • Create MVC 4 web application
  • SQL Express – Adventure Works Departments
  • Add “AdventureWorks.edmx
    • Wizard driven
    • F4 set namespace
  • Add “DepartmentsController.cs
    • Create from EDMX class
    • Implements ODataController
    • Replace ID with KEY
  • Edit “WebApiConfig.cs
    • Comment out default route
    • Add OData route builder
  • Test with HTTP manually
  • Test with Chrome REST Postman
  • SQL Express – see changed data

Watch Video

WebAPI OData – 10 min video introduction (Visual Studio 2013) from Jeff Jones on Vimeo.

Sample Code

[WebApiConfig.cs]

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using System.Web.Http.OData.Builder;
namespace MvcApplication1
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            //config.Routes.MapHttpRoute(
            //    name: "DefaultApi",
            //    routeTemplate: "api/{controller}/{id}",
            //    defaults: new { id = RouteParameter.Optional }
            //);
            ODataConventionModelBuilder build = new ODataConventionModelBuilder();
            build.EntitySet("Departments");
            config.Routes.MapODataRoute("odata", "odata", build.GetEdmModel());
            config.EnableQuerySupport(new QueryableAttribute()); 
            // Uncomment the following line of code to enable query support for actions with an IQueryable or IQueryable return type.
            // To avoid processing unexpected or malicious queries, use the validation settings on QueryableAttribute to validate incoming queries.
            // For more information, visit http://go.microsoft.com/fwlink/?LinkId=279712.
            //config.EnableQuerySupport();
            // To disable tracing in your application, please comment out or remove the following line of code
            // For more information, refer to: http://www.asp.net/web-api
            config.EnableSystemDiagnosticsTracing();
        }
    }
}

 

[DepartmentsController.cs]

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web;
using System.Web.Http;
using System.Web.Http.OData;
namespace MvcApplication1.Controllers
{
    public class DepartmentsController : ODataController
    {
        private AdventureWorks2012Entities db = new AdventureWorks2012Entities();
        // GET api/Default1
        public IEnumerable GetDepartments()
        {
            return db.Departments.AsEnumerable();
        }
        // GET api/Default1/5
        public Department GetDepartment(short key)
        {
            Department department = db.Departments.Find(key);
            if (department == null)
            {
                throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
            }
            return department;
        }
        // PUT api/Default1/5
        public HttpResponseMessage PutDepartment(short key, Department department)
        {
            if (!ModelState.IsValid)
            {
                return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
            }
            if (key != department.DepartmentID)
            {
                return Request.CreateResponse(HttpStatusCode.BadRequest);
            }
            db.Entry(department).State = EntityState.Modified;
            try
            {
                db.SaveChanges();
            }
            catch (DbUpdateConcurrencyException ex)
            {
                return Request.CreateErrorResponse(HttpStatusCode.NotFound, ex);
            }
            return Request.CreateResponse(HttpStatusCode.OK);
        }
        // POST api/Default1
        public HttpResponseMessage PostDepartment(Department department)
        {
            if (ModelState.IsValid)
            {
                db.Departments.Add(department);
                db.SaveChanges();
                HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, department);
                response.Headers.Location = new Uri(Url.Link("odata", new { key = department.DepartmentID }));
                return response;
            }
            else
            {
                return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
            }
        }
        // DELETE api/Default1/5
        public HttpResponseMessage DeleteDepartment(short key)
        {
            Department department = db.Departments.Find(key);
            if (department == null)
            {
                return Request.CreateResponse(HttpStatusCode.NotFound);
            }
            db.Departments.Remove(department);
            try
            {
                db.SaveChanges();
            }
            catch (DbUpdateConcurrencyException ex)
            {
                return Request.CreateErrorResponse(HttpStatusCode.NotFound, ex);
            }
            return Request.CreateResponse(HttpStatusCode.OK, department);
        }
        protected override void Dispose(bool disposing)
        {
            db.Dispose();
            base.Dispose(disposing);
        }
    }
}

Downloads

Screenshots

image
image
image
image
image

© Copyright 2016
@ SPJeff

Return to Top ▲Return to Top ▲