Merge pull request #1753 from umbraco/temp-U4-9293

Fixes: U4-9293 Search the entire media section in Media Picker when inserting an image into content
This commit is contained in:
Emil Wangaa
2017-02-21 12:00:26 +01:00
committed by GitHub
10 changed files with 568 additions and 44 deletions

View File

@@ -396,7 +396,7 @@ namespace Umbraco.Core.Services
using (var uow = UowProvider.GetUnitOfWork())
{
var repository = RepositoryFactory.CreateEntityRepository(uow);
var query = Query<IUmbracoEntity>.Builder.Where(x => x.ParentId == parentId);
var query = Query<IUmbracoEntity>.Builder.Where(x => x.ParentId == parentId && x.Trashed == false);
IQuery<IUmbracoEntity> filterQuery = null;
if (filter.IsNullOrWhiteSpace() == false)
@@ -410,6 +410,18 @@ namespace Umbraco.Core.Services
}
}
/// <summary>
/// Returns a paged collection of descendants
/// </summary>
/// <param name="id"></param>
/// <param name="umbracoObjectType"></param>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <param name="totalRecords"></param>
/// <param name="orderBy"></param>
/// <param name="orderDirection"></param>
/// <param name="filter"></param>
/// <returns></returns>
public IEnumerable<IUmbracoEntity> GetPagedDescendants(int id, UmbracoObjectTypes umbracoObjectType, long pageIndex, int pageSize, out long totalRecords,
string orderBy = "path", Direction orderDirection = Direction.Ascending, string filter = "")
{
@@ -421,8 +433,45 @@ namespace Umbraco.Core.Services
var query = Query<IUmbracoEntity>.Builder;
//if the id is System Root, then just get all
if (id != Constants.System.Root)
query.Where(x => x.Path.SqlContains(string.Format(",{0},", id), TextColumnType.NVarchar));
IQuery<IUmbracoEntity> filterQuery = null;
if (filter.IsNullOrWhiteSpace() == false)
{
query.Where(x => x.Path.SqlContains(string.Format(",{0},", id), TextColumnType.NVarchar));
filterQuery = Query<IUmbracoEntity>.Builder.Where(x => x.Name.Contains(filter));
}
var contents = repository.GetPagedResultsByQuery(query, objectTypeId, pageIndex, pageSize, out totalRecords, orderBy, orderDirection, filterQuery);
uow.Commit();
return contents;
}
}
/// <summary>
/// Returns a paged collection of descendants from the root
/// </summary>
/// <param name="umbracoObjectType"></param>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <param name="totalRecords"></param>
/// <param name="orderBy"></param>
/// <param name="orderDirection"></param>
/// <param name="filter"></param>
/// <param name="includeTrashed">true/false to include trashed objects</param>
/// <returns></returns>
public IEnumerable<IUmbracoEntity> GetPagedDescendantsFromRoot(UmbracoObjectTypes umbracoObjectType, long pageIndex, int pageSize, out long totalRecords,
string orderBy = "path", Direction orderDirection = Direction.Ascending, string filter = "", bool includeTrashed = true)
{
var objectTypeId = umbracoObjectType.GetGuid();
using (var uow = UowProvider.GetUnitOfWork())
{
var repository = RepositoryFactory.CreateEntityRepository(uow);
var query = Query<IUmbracoEntity>.Builder;
//don't include trashed if specfied
if (includeTrashed == false)
{
query.Where(x => x.Trashed == false);
}
IQuery<IUmbracoEntity> filterQuery = null;

View File

@@ -153,9 +153,36 @@ namespace Umbraco.Core.Services
IEnumerable<IUmbracoEntity> GetPagedChildren(int parentId, UmbracoObjectTypes umbracoObjectType, long pageIndex, int pageSize, out long totalRecords,
string orderBy = "SortOrder", Direction orderDirection = Direction.Ascending, string filter = "");
/// <summary>
/// Returns a paged collection of descendants
/// </summary>
/// <param name="id"></param>
/// <param name="umbracoObjectType"></param>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <param name="totalRecords"></param>
/// <param name="orderBy"></param>
/// <param name="orderDirection"></param>
/// <param name="filter"></param>
/// <returns></returns>
IEnumerable<IUmbracoEntity> GetPagedDescendants(int id, UmbracoObjectTypes umbracoObjectType, long pageIndex, int pageSize, out long totalRecords,
string orderBy = "path", Direction orderDirection = Direction.Ascending, string filter = "");
/// <summary>
/// Returns a paged collection of descendants from the root
/// </summary>
/// <param name="umbracoObjectType"></param>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <param name="totalRecords"></param>
/// <param name="orderBy"></param>
/// <param name="orderDirection"></param>
/// <param name="filter"></param>
/// <param name="includeTrashed">true/false to include trashed objects</param>
/// <returns></returns>
IEnumerable<IUmbracoEntity> GetPagedDescendantsFromRoot(UmbracoObjectTypes umbracoObjectType, long pageIndex, int pageSize, out long totalRecords,
string orderBy = "path", Direction orderDirection = Direction.Ascending, string filter = "", bool includeTrashed = true);
/// <summary>
/// Gets a collection of descendents by the parents Id
/// </summary>

View File

@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using Umbraco.Core;
@@ -25,7 +26,7 @@ namespace Umbraco.Tests.Services
public override void TearDown()
{
base.TearDown();
}
}
[Test]
public void EntityService_Can_Get_Paged_Content_Children()
@@ -85,6 +86,94 @@ namespace Umbraco.Tests.Services
Assert.That(total, Is.EqualTo(60));
}
[Test]
public void EntityService_Can_Get_Paged_Content_Descendants_Including_Recycled()
{
var contentType = ServiceContext.ContentTypeService.GetContentType("umbTextpage");
var root = MockedContent.CreateSimpleContent(contentType);
ServiceContext.ContentService.Save(root);
var toDelete = new List<IContent>();
for (int i = 0; i < 10; i++)
{
var c1 = MockedContent.CreateSimpleContent(contentType, Guid.NewGuid().ToString(), root);
ServiceContext.ContentService.Save(c1);
if (i % 2 == 0)
{
toDelete.Add(c1);
}
for (int j = 0; j < 5; j++)
{
var c2 = MockedContent.CreateSimpleContent(contentType, Guid.NewGuid().ToString(), c1);
ServiceContext.ContentService.Save(c2);
}
}
foreach (var content in toDelete)
{
ServiceContext.ContentService.MoveToRecycleBin(content);
}
var service = ServiceContext.EntityService;
long total;
//search at root to see if it returns recycled
var entities = service.GetPagedDescendants(-1, UmbracoObjectTypes.Document, 0, 1000, out total)
.Select(x => x.Id)
.ToArray();
foreach (var c in toDelete)
{
Assert.True(entities.Contains(c.Id));
}
}
[Test]
public void EntityService_Can_Get_Paged_Content_Descendants_Without_Recycled()
{
var contentType = ServiceContext.ContentTypeService.GetContentType("umbTextpage");
var root = MockedContent.CreateSimpleContent(contentType);
ServiceContext.ContentService.Save(root);
var toDelete = new List<IContent>();
for (int i = 0; i < 10; i++)
{
var c1 = MockedContent.CreateSimpleContent(contentType, Guid.NewGuid().ToString(), root);
ServiceContext.ContentService.Save(c1);
if (i % 2 == 0)
{
toDelete.Add(c1);
}
for (int j = 0; j < 5; j++)
{
var c2 = MockedContent.CreateSimpleContent(contentType, Guid.NewGuid().ToString(), c1);
ServiceContext.ContentService.Save(c2);
}
}
foreach (var content in toDelete)
{
ServiceContext.ContentService.MoveToRecycleBin(content);
}
var service = ServiceContext.EntityService;
long total;
//search at root to see if it returns recycled
var entities = service.GetPagedDescendantsFromRoot(UmbracoObjectTypes.Document, 0, 1000, out total, includeTrashed:false)
.Select(x => x.Id)
.ToArray();
foreach (var c in toDelete)
{
Assert.IsFalse(entities.Contains(c.Id));
}
}
[Test]
public void EntityService_Can_Get_Paged_Content_Descendants_With_Search()
{
@@ -115,7 +204,7 @@ namespace Umbraco.Tests.Services
Assert.That(entities.Length, Is.EqualTo(50));
Assert.That(total, Is.EqualTo(50));
}
[Test]
public void EntityService_Can_Get_Paged_Media_Children()
{
@@ -175,6 +264,96 @@ namespace Umbraco.Tests.Services
Assert.That(total, Is.EqualTo(60));
}
[Test]
public void EntityService_Can_Get_Paged_Media_Descendants_Including_Recycled()
{
var folderType = ServiceContext.ContentTypeService.GetMediaType(1031);
var imageMediaType = ServiceContext.ContentTypeService.GetMediaType(1032);
var root = MockedMedia.CreateMediaFolder(folderType, -1);
ServiceContext.MediaService.Save(root);
var toDelete = new List<IMedia>();
for (int i = 0; i < 10; i++)
{
var c1 = MockedMedia.CreateMediaImage(imageMediaType, root.Id);
ServiceContext.MediaService.Save(c1);
if (i % 2 == 0)
{
toDelete.Add(c1);
}
for (int j = 0; j < 5; j++)
{
var c2 = MockedMedia.CreateMediaImage(imageMediaType, c1.Id);
ServiceContext.MediaService.Save(c2);
}
}
foreach (var content in toDelete)
{
ServiceContext.MediaService.MoveToRecycleBin(content);
}
var service = ServiceContext.EntityService;
long total;
//search at root to see if it returns recycled
var entities = service.GetPagedDescendants(-1, UmbracoObjectTypes.Media, 0, 1000, out total)
.Select(x => x.Id)
.ToArray();
foreach (var media in toDelete)
{
Assert.IsTrue(entities.Contains(media.Id));
}
}
[Test]
public void EntityService_Can_Get_Paged_Media_Descendants_Without_Recycled()
{
var folderType = ServiceContext.ContentTypeService.GetMediaType(1031);
var imageMediaType = ServiceContext.ContentTypeService.GetMediaType(1032);
var root = MockedMedia.CreateMediaFolder(folderType, -1);
ServiceContext.MediaService.Save(root);
var toDelete = new List<IMedia>();
for (int i = 0; i < 10; i++)
{
var c1 = MockedMedia.CreateMediaImage(imageMediaType, root.Id);
ServiceContext.MediaService.Save(c1);
if (i % 2 == 0)
{
toDelete.Add(c1);
}
for (int j = 0; j < 5; j++)
{
var c2 = MockedMedia.CreateMediaImage(imageMediaType, c1.Id);
ServiceContext.MediaService.Save(c2);
}
}
foreach (var content in toDelete)
{
ServiceContext.MediaService.MoveToRecycleBin(content);
}
var service = ServiceContext.EntityService;
long total;
//search at root to see if it returns recycled
var entities = service.GetPagedDescendantsFromRoot(UmbracoObjectTypes.Media, 0, 1000, out total, includeTrashed:false)
.Select(x => x.Id)
.ToArray();
foreach (var media in toDelete)
{
Assert.IsFalse(entities.Contains(media.Id));
}
}
[Test]
public void EntityService_Can_Get_Paged_Media_Descendants_With_Search()
{

View File

@@ -346,8 +346,8 @@ function entityResource($q, $http, umbRequestHelper) {
* @param {Int} parentid id of content item to return children of
* @param {string} type Object type name
* @param {Object} options optional options object
* @param {Int} options.pageSize if paging data, number of nodes per page, default = 0
* @param {Int} options.pageNumber if paging data, current page index, default = 0
* @param {Int} options.pageSize if paging data, number of nodes per page, default = 1
* @param {Int} options.pageNumber if paging data, current page index, default = 100
* @param {String} options.filter if provided, query will only return those with names matching the filter
* @param {String} options.orderDirection can be `Ascending` or `Descending` - Default: `Ascending`
* @param {String} options.orderBy property to order items by, default: `SortOrder`
@@ -357,8 +357,8 @@ function entityResource($q, $http, umbRequestHelper) {
getPagedChildren: function (parentId, type, options) {
var defaults = {
pageSize: 0,
pageNumber: 0,
pageSize: 1,
pageNumber: 100,
filter: '',
orderDirection: "Ascending",
orderBy: "SortOrder"
@@ -390,7 +390,77 @@ function entityResource($q, $http, umbRequestHelper) {
pageSize: options.pageSize,
orderBy: options.orderBy,
orderDirection: options.orderDirection,
filter: options.filter
filter: encodeURIComponent(options.filter)
}
)),
'Failed to retrieve child data for id ' + parentId);
},
/**
* @ngdoc method
* @name umbraco.resources.entityResource#getPagedDescendants
* @methodOf umbraco.resources.entityResource
*
* @description
* Gets paged descendants of a content item with a given id
*
* ##usage
* <pre>
* entityResource.getPagedDescendants(1234, "Content", {pageSize: 10, pageNumber: 2})
* .then(function(contentArray) {
* var children = contentArray;
* alert('they are here!');
* });
* </pre>
*
* @param {Int} parentid id of content item to return descendants of
* @param {string} type Object type name
* @param {Object} options optional options object
* @param {Int} options.pageSize if paging data, number of nodes per page, default = 1
* @param {Int} options.pageNumber if paging data, current page index, default = 100
* @param {String} options.filter if provided, query will only return those with names matching the filter
* @param {String} options.orderDirection can be `Ascending` or `Descending` - Default: `Ascending`
* @param {String} options.orderBy property to order items by, default: `SortOrder`
* @returns {Promise} resourcePromise object containing an array of content items.
*
*/
getPagedDescendants: function (parentId, type, options) {
var defaults = {
pageSize: 1,
pageNumber: 100,
filter: '',
orderDirection: "Ascending",
orderBy: "SortOrder"
};
if (options === undefined) {
options = {};
}
//overwrite the defaults if there are any specified
angular.extend(defaults, options);
//now copy back to the options we will use
options = defaults;
//change asc/desct
if (options.orderDirection === "asc") {
options.orderDirection = "Ascending";
}
else if (options.orderDirection === "desc") {
options.orderDirection = "Descending";
}
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"entityApiBaseUrl",
"GetPagedDescendants",
{
id: parentId,
type: type,
pageNumber: options.pageNumber,
pageSize: options.pageSize,
orderBy: options.orderBy,
orderDirection: options.orderDirection,
filter: encodeURIComponent(options.filter)
}
)),
'Failed to retrieve child data for id ' + parentId);

View File

@@ -482,7 +482,49 @@ function mediaResource($q, $http, umbDataFormatter, umbRequestHelper) {
"mediaApiBaseUrl",
"EmptyRecycleBin")),
'Failed to empty the recycle bin');
},
/**
* @ngdoc method
* @name umbraco.resources.mediaResource#search
* @methodOf umbraco.resources.mediaResource
*
* @description
* Empties the media recycle bin
*
* ##usage
* <pre>
* mediaResource.search("my search", 1, 100, -1)
* .then(function(searchResult) {
* alert('it's here!');
* });
* </pre>
*
* @param {string} query The search query
* @param {int} pageNumber The page number
* @param {int} pageSize The number of media items on a page
* @param {int} searchFrom Id to search from
* @returns {Promise} resourcePromise object.
*
*/
search: function (query, pageNumber, pageSize, searchFrom) {
var args = [
{ "query": query },
{ "pageNumber": pageNumber },
{ "pageSize": pageSize },
{ "searchFrom": searchFrom }
];
return umbRequestHelper.resourcePromise(
$http.get(
umbRequestHelper.getApiUrl(
"mediaApiBaseUrl",
"Search",
args)),
'Failed to retrieve media items for search: ' + query);
}
};
}

View File

@@ -33,6 +33,14 @@ angular.module("umbraco")
$scope.acceptedMediatypes = types;
});
$scope.searchOptions = {
pageNumber: 1,
pageSize: 100,
totalItems: 0,
totalPages: 0,
filter: '',
};
//preload selected item
$scope.target = undefined;
if (dialogOptions.currentTarget) {
@@ -106,35 +114,9 @@ angular.module("umbraco")
$scope.path = [];
}
//mediaResource.rootMedia()
mediaResource.getChildren(folder.id)
.then(function(data) {
$scope.searchTerm = "";
$scope.images = data.items ? data.items : [];
// set already selected images to selected
for (var folderImageIndex = 0; folderImageIndex < $scope.images.length; folderImageIndex++) {
var folderImage = $scope.images[folderImageIndex];
var imageIsSelected = false;
for (var selectedImageIndex = 0;
selectedImageIndex < $scope.model.selectedImages.length;
selectedImageIndex++) {
var selectedImage = $scope.model.selectedImages[selectedImageIndex];
if (folderImage.key === selectedImage.key) {
imageIsSelected = true;
}
}
if (imageIsSelected) {
folderImage.selected = true;
}
}
});
getChildren(folder.id);
$scope.currentFolder = folder;
localStorageService.set("umbLastOpenedMediaNodeId", folder.id);
};
$scope.clickHandler = function(image, event, index) {
@@ -238,4 +220,106 @@ angular.module("umbraco")
$scope.mediaPickerDetailsOverlay = null;
};
};
$scope.changeSearch = function() {
$scope.loading = true;
debounceSearchMedia();
};
$scope.changePagination = function(pageNumber) {
$scope.loading = true;
$scope.searchOptions.pageNumber = pageNumber;
searchMedia();
};
var debounceSearchMedia = _.debounce(function () {
$scope.$apply(function () {
if ($scope.searchOptions.filter) {
searchMedia();
} else {
// reset pagination
$scope.searchOptions = {
pageNumber: 1,
pageSize: 100,
totalItems: 0,
totalPages: 0,
filter: ''
};
getChildren($scope.currentFolder.id);
}
});
}, 500);
function searchMedia() {
$scope.loading = true;
entityResource.getPagedDescendants($scope.startNodeId, "Media", $scope.searchOptions)
.then(function (data) {
// update image data to work with image grid
angular.forEach(data.items, function(mediaItem){
// set thumbnail and src
mediaItem.thumbnail = mediaHelper.resolveFileFromEntity(mediaItem, true);
mediaItem.image = mediaHelper.resolveFileFromEntity(mediaItem, false);
// set properties to match a media object
if (mediaItem.metaData &&
mediaItem.metaData.umbracoWidth &&
mediaItem.metaData.umbracoHeight) {
mediaItem.properties = [
{
alias: "umbracoWidth",
value: mediaItem.metaData.umbracoWidth.Value
},
{
alias: "umbracoHeight",
value: mediaItem.metaData.umbracoHeight.Value
}
];
}
});
// update images
$scope.images = data.items ? data.items : [];
// update pagination
if (data.pageNumber > 0)
$scope.searchOptions.pageNumber = data.pageNumber;
if (data.pageSize > 0)
$scope.searchOptions.pageSize = data.pageSize;
$scope.searchOptions.totalItems = data.totalItems;
$scope.searchOptions.totalPages = data.totalPages;
// set already selected images to selected
preSelectImages();
$scope.loading = false;
});
}
function getChildren(id) {
$scope.loading = true;
mediaResource.getChildren(id)
.then(function(data) {
$scope.searchOptions.filter = "";
$scope.images = data.items ? data.items : [];
// set already selected images to selected
preSelectImages();
$scope.loading = false;
});
}
function preSelectImages() {
for (var folderImageIndex = 0; folderImageIndex < $scope.images.length; folderImageIndex++) {
var folderImage = $scope.images[folderImageIndex];
var imageIsSelected = false;
for (var selectedImageIndex = 0;
selectedImageIndex < $scope.model.selectedImages.length;
selectedImageIndex++) {
var selectedImage = $scope.model.selectedImages[selectedImageIndex];
if (folderImage.key === selectedImage.key) {
imageIsSelected = true;
}
}
if (imageIsSelected) {
folderImage.selected = true;
}
}
}
});

View File

@@ -10,13 +10,18 @@
<div class="umb-control-group umb-mediapicker-upload">
<umb-load-indicator
ng-if="loading">
</umb-load-indicator>
<div class="form-search">
<i class="icon-search"></i>
<input
class="umb-search-field search-query"
ng-model="searchTerm"
class="umb-search-field search-query -full-width-input"
ng-model="searchOptions.filter"
localize="placeholder"
placeholder="@placeholders_filter"
placeholder="@placeholders_search"
ng-change="changeSearch()"
type="text">
</div>
@@ -32,7 +37,7 @@
</div>
<div class="row umb-control-group">
<div class="row umb-control-group" ng-if="!searchOptions.filter">
<ul class="umb-breadcrumbs">
<li ng-hide="startNodeId != -1" class="umb-breadcrumbs__ancestor">
<a href ng-click="gotoFolder()" prevent-default>Media</a>
@@ -63,20 +68,20 @@
</div>
<umb-file-dropzone
ng-if="acceptedMediatypes.length > 0"
ng-if="acceptedMediatypes.length > 0 && !loading"
accepted-mediatypes="acceptedMediatypes"
parent-id="{{currentFolder.id}}"
files-uploaded="onUploadComplete"
files-queued="onFilesQueue"
accept="{{acceptedFileTypes}}"
max-file-size="{{maxFileSize}}"
hide-dropzone="{{!activeDrag && images.length > 0 }}"
hide-dropzone="{{!activeDrag && images.length > 0 || searchOptions.filter }}"
compact="{{ images.length > 0 }}">
</umb-file-dropzone>
<umb-media-grid
ng-if="!loading"
items="images"
filter-by="searchTerm"
on-click="clickHandler"
on-click-name="clickItemName"
item-max-width="150"
@@ -86,6 +91,21 @@
only-images={{onlyImages}}>
</umb-media-grid>
<div class="flex justify-center">
<umb-pagination
ng-if="searchOptions.totalPages > 0 && !loading"
page-number="searchOptions.pageNumber"
total-pages="searchOptions.totalPages"
on-change="changePagination(pageNumber)">
</umb-pagination>
</div>
<umb-empty-state
ng-if="searchOptions.filter && images.length === 0 && !loading"
position="center">
<localize key="general_searchNoResult"></localize>
</umb-empty-state>
</div>
<umb-overlay

View File

@@ -483,7 +483,7 @@ function listViewController($rootScope, $scope, $routeParams, $injector, $cookie
//we need to do a double sync here: first refresh the node where the content was moved,
// then refresh the node where the content was moved from
navigationService.syncTree({
tree: target.nodeType,
tree: target.nodeType ? target.nodeType : (target.metaData.treeAlias),
path: newPath,
forceReload: true,
activate: false

View File

@@ -508,6 +508,56 @@ namespace Umbraco.Web.Editors
}
}
public PagedResult<EntityBasic> GetPagedDescendants(
int id,
UmbracoEntityTypes type,
int pageNumber,
int pageSize,
string orderBy = "SortOrder",
Direction orderDirection = Direction.Ascending,
string filter = "")
{
if (pageNumber <= 0)
throw new HttpResponseException(HttpStatusCode.NotFound);
if (pageSize <= 0)
throw new HttpResponseException(HttpStatusCode.NotFound);
var objectType = ConvertToObjectType(type);
if (objectType.HasValue)
{
long totalRecords;
//if it's from root, don't return recycled
var entities = id == Constants.System.Root
? Services.EntityService.GetPagedDescendantsFromRoot(objectType.Value, pageNumber - 1, pageSize, out totalRecords, orderBy, orderDirection, filter, includeTrashed:false)
: Services.EntityService.GetPagedDescendants(id, objectType.Value, pageNumber - 1, pageSize, out totalRecords, orderBy, orderDirection, filter);
if (totalRecords == 0)
{
return new PagedResult<EntityBasic>(0, 0, 0);
}
var pagedResult = new PagedResult<EntityBasic>(totalRecords, pageNumber, pageSize)
{
Items = entities.Select(Mapper.Map<EntityBasic>)
};
return pagedResult;
}
//now we need to convert the unknown ones
switch (type)
{
case UmbracoEntityTypes.PropertyType:
case UmbracoEntityTypes.PropertyGroup:
case UmbracoEntityTypes.Domain:
case UmbracoEntityTypes.Language:
case UmbracoEntityTypes.User:
case UmbracoEntityTypes.Macro:
default:
throw new NotSupportedException("The " + typeof(EntityController) + " does not currently support data for the type " + type);
}
}
public IEnumerable<EntityBasic> GetAncestors(int id, UmbracoEntityTypes type)
{
return GetResultForAncestors(id, type);

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.IO;
using System.Net;
using System.Net.Http;
@@ -28,7 +29,9 @@ using Umbraco.Web.Mvc;
using Umbraco.Web.WebApi;
using System.Linq;
using System.Runtime.Serialization;
using System.Text.RegularExpressions;
using System.Web.Http.Controllers;
using Examine;
using Umbraco.Web.WebApi.Binders;
using Umbraco.Web.WebApi.Filters;
using umbraco;