- SharePoint 2013 REST API
- Introducing BreezeJS
- So, How to Set it Up?
- What's Next for BreezeJS & SharePoint?
- Introduced with read/write support for lists in SharePoint 2010
http://intranet.contoso.com/_layouts/ListData.svc
- Dramatically expanded in SharePoint 2013 to support more than lists
- Based on OData v3.0 but contains some oddities & inconsistencies
- Full control over payload
- Standard response type
- Consumers can use any technology on any platform
- Have to write all the plumbing
- More chatty than CSOM
- CSOM is a proxy wrapper around the same endpoint
- Only available to .NET, Silverlight & JavaScript
- Not available to other technologies
- Returns SharePoint objects
- Very few 3rd party libraries written for SharePoint objects
- Point to the collection & get all
var requestUri = _spPageContextInfo.webAbsoluteUrl +'/_api/Web/Lists'
+'/getByTitle(\'Contacts\')/items/?'
+'$select=Id,FirstName,Title,Email';
// execute AJAX request
var requestHeaders = {
'ACCEPT': 'application/json;odata=verbose'
};
jQuery.ajax({
url: requestUri,
headers: requestHeaders,
success: function (response){ /* do something on success */ },
error: function(error){ /* do something on fail */ }
});
- Just like Get Many Items but point to specific resource
var requestUri = _spPageContextInfo.webAbsoluteUrl + '/_api/Web/Lists'
+'/getByTitle(\'Contacts\')/items/?'
+'$select=Id,FirstName,Title,Email' + '&$filter=Id eq 1';
// execute AJAX request
var requestHeaders = {
'ACCEPT': 'application/json;odata=verbose'
};
jQuery.ajax({
url: requestUri,
headers: requestHeaders,
success: function (response){ /* do something on success */ },
error: function(error){ /* do something on fail */ }
});
- Point to collection
- Send object to create (matching metadata) via HTTP POST
- Include
X-REQUEST-DIGEST
header
var requestUri = _spPageContextInfo.webAbsoluteUrl + '/_api/Web/Lists'
+'/getByTitle(\'Contacts\')/items';
var requestHeaders = {
'ACCEPT': 'application/json;odata=verbose',
'X-RequestDigest': $('#__REQUESTDIGEST').val(),
};
var customerData = {
__metadata: {
'type': 'SP.Data.ContactsListItem'
},
Title: 'Name'
};
requestBody = JSON.stringify(customerData);
jQuery.ajax({
url: requestUri,
type: 'POST',
contentType: 'application/json;odata=verbose',
headers: requestHeaders,
data: JSON.stringify(customerData),
success: function (response){ /* do something on success */ },
error: function(error){ /* do something on fail */ }
});
- Point to specific resource you want to update
- Send object to create (matching metadata) via HTTP POST
- If updating only fields submitted, include
X-HTTP-METHOD
header set to MERGE - Include
X-REQUEST-DIGEST
header - Include
IF-MATCH
header so updating intended version
var requestUri = _spPageContextInfo.webAbsoluteUrl + '/_api/Web/Lists'
+'/getByTitle(\'Contacts\')/items(1)';
var requestHeaders = {
'ACCEPT': 'application/json;odata=verbose',
'X-RequestDigest': $('#__REQUESTDIGEST').val(),
'X-HTTP-Method': 'MERGE',
'If-Match': etag
};
var customerData = {
__metadata: {
'type': 'SP.Data.ContactsListItem'
},
Title: 'NewName'
};
requestBody = JSON.stringify(customerData);
jQuery.ajax({
url: requestUri,
type: 'POST',
contentType: 'application/json;odata=verbose',
headers: requestHeaders,
data: requestBody,
success: function (response){ /* do something on success */ },
error: function(error){ /* do something on fail */ }
});
- Point to specific resource you want to delete
- Use HTTP DELETE
- Include
X-REQUEST-DIGEST
header - Include
IF-MATCH
header with*
value
var requestUri = _spPageContextInfo.webAbsoluteUrl + '/_api/Web/Lists'
+'/getByTitle(\'Contacts\')/items(1)';
var requestHeaders = {
'ACCEPT': 'application/json;odata=verbose',
'X-RequestDigest': $('#__REQUESTDIGEST').val(),
'If-Match': '*'
};
jQuery.ajax({
url: requestUri,
type: 'DELETE',
headers: requestHeaders,
success: function (response){ /* do something on success */ },
error: function(error){ /* do something on fail */ }
});
- Think "ORM / Entity Framework in JavaScript"
- LINQ-style query syntax
- All async calls return promises
- Query & navigate to related entities
- Query locally with automatic client side caching
- Client-side entity validation
- Client-side change tracking
- Client & server component
- Validation
- Customizable - data service adapter pattern
- OData
- WebAPI
- WebAPIOData
- SharePoint
- Breeze Labs
- AngularJS directives
- Helpers
- Custom data service adapters
Doesn't work out of the box
- No support for
$batch
- Invalid
$metadata
response
- For HTTP POST, PUT, DELETE must include
X-RequestDigest
in header - Doesn't support HTTP PATCH / MERGE
- Uses
X-MERGE-METHOD
header instead
- Uses
- Created custom BreezeJS data service adapter for SharePoint
- Overrides communication between BeezeJS & SharePoint
- Configure Breeze for manual metadata store creation (not automatic)
- All included in NuGet package - Breeze.DataService.SharePoint
- Includes everything you need, including BreezeJS client
- Requires a little setup work, but only required once per project
After the one time setup...
var contactType = metadataStore.getEntityType('Contact');
var queryAsPromise = breeze.EntityQuery
.from(contactType.defaultResourceName)
.using(entityManager)
.execute();
After the one time setup...
// try to get a single item from the cache, then revert to server
var queryAsPromise = entityManager.fetchEntityByKey('Contact', 1, true);
// handling response example
queryAsPromise.then(function(data){
var actualEntity = data.entity;
var message = "data retrieved from: "
if (data.fromCache){
message += "client-side cache";
} else {
message += "server-side REST call";
}
});
After the one time setup...
// get reference to our entity type...
var entityType = metadataStore.getEntityType('Contact');
// create instance of the entity
var newEntity = entityManager.createEntity(entityType, initialValues)
newEntity.Title = "some title";
// save entity to server
var resultPromise = entityManager.saveChanges();
After the one time setup...
var entity = // some query to get an item
// update entity
entity.Title = "new title";
// save changes to server
var resultPromise = entityManager.saveChanges();
// or cancel... reset dirty flag & entity to original data
var resultPromise = entityManager.rejectChanges();
After the one time setup...
var entity = // some query to get an item
// update entity
entity.entityAspect.setDeleted();
// save changes to server
var resultPromise = entityManager.saveChanges();
// or cancel... reset dirty flag & entity to original data
var resultPromise = entityManager.rejectChanges();
Only 4 easy steps...
- Apply the NuGet package to your project - Breeze.DataService.SharePoint
- Configure BreezeJS SharePoint data service adapter
- Create & populate the BreezeJS metadata store
- Initialize BreezeJS
Install-Package "Breeze.DataService.SharePoint"
// configure breeze to use SharePoint OData service
var dsAdapter = breeze.config.initializeAdapterInstance('dataService', 'SharePointOData', true);
// tell breeze how to get the security validation token for
// HTTP POST & DELETE calls
dsAdapter.getRequestDigest = function () {
return jQuery('#__REQUESTDIGEST').val();
};
// create a new breeze metadata store
metadataStore = new breeze.MetadataStore();
// setup a helper to create entities
var namespace = '';
var helper = new breeze.config.MetadataHelper(namespace, breeze.AutoGeneratedKeyType.Identity);
// create entity for contacts
var contactEntity = {
name: 'Contact',
defaultResourceName: 'getbytitle(\'Contacts\')/items',
dataProperties: {
Id: { type: breeze.DataType.Int32 },
FirstName: { nullable: false },
Title: { nullable: false }, // this is actually the last name field in the list
Email: {
nullable: false,
validators: [breeze.Validator.emailAddress()]
}
}
};
// add entity to metadata store
helper.addTypeToStore(metadataStore, contactEntity);
// get reference to contact entity type
contactType = metadataStore.getEntityType('Contact');
// create the data service
var dataService = new breeze.DataService({
// tell breeze the root REST endpoint to use
// since we only are using lists, point to that
serviceName: _spPageContextInfo.webAbsoluteUrl + '/_api/web/lists/',
// tell breeze not to interrogate sharepoint for it's
// massive OData $metadata response... we created it manually
hasServerMetadata: false
});
// create an instance of the entity manager
entityManager = new breeze.EntityManager({
dataService: dataService,
// tell breeze where the metadata is
metadataStore: metadataStore
});
- SharePoint 2010
listdata.svc
REST support - issue #2 - SharePoint 2013 cross domain support - issue #4
- Simplify setup & registration
- Entity metadata generation
- Follow my blog or me on Twitter @andrewconnell
- Follow my fork of the BreezeJS Labs repo
- github.com/andrewconnell/breeze.js.labs
- All issues, enhancements & milestones in issues list
- Contribute, follow, report bugs
- Edits sent back to BreezeJS pull requests & new drops ship every few weeks
#Resources
- AC's Blog Posts
- What are Breeze Labs?
- Demo project
- BreezeJS Labs fork for SharePoint data service adapter development