forked from OData/RESTier
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
334 additions
and
54 deletions.
There are no files selected for viewing
206 changes: 206 additions & 0 deletions
206
...taEndToEnd/Microsoft.OData.Service.Sample.TrippinInMemory/Controllers/PeopleController.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,206 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. See License.txt in the project root for license information. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Net; | ||
using System.Web.Http; | ||
using System.Web.OData; | ||
using System.Web.OData.Extensions; | ||
using System.Web.OData.Routing; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Microsoft.OData.Edm; | ||
using Microsoft.OData.Service.Sample.TrippinInMemory.Api; | ||
using Microsoft.OData.Service.Sample.TrippinInMemory.Models; | ||
using Microsoft.Restier.Core; | ||
|
||
namespace Microsoft.OData.Service.Sample.TrippinInMemory.Controllers | ||
{ | ||
public class PeopleController : ODataController | ||
{ | ||
private TrippinApi _api; | ||
private TrippinApi Api | ||
{ | ||
get | ||
{ | ||
if (_api == null) | ||
{ | ||
_api = (TrippinApi)this.Request.GetRequestContainer().GetService<ApiBase>(); | ||
} | ||
|
||
return _api; | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Restier only supports put and post entity set. | ||
/// Use property name to simulate the bound action. | ||
/// </summary> | ||
/// <param name="key">Key of people entity set, parsed from uri.</param> | ||
/// <param name="name">The value of last name to be updated.</param> | ||
/// <returns><see cref="IHttpActionResult"></returns> | ||
[HttpPut] | ||
[ODataRoute("People({key})/LastName")] | ||
public IHttpActionResult UpdatePersonLastName([FromODataUri]string key, [FromBody] string name) | ||
{ | ||
var person = Api.People.Single(p => p.UserName == key); | ||
if (Api.UpdatePersonLastName(person, name)) | ||
{ | ||
return Ok(); | ||
} | ||
else | ||
{ | ||
return NotFound(); | ||
} | ||
} | ||
|
||
[HttpGet] | ||
[ODataRoute("People({key})/Friends/$ref")] | ||
public IHttpActionResult GetRefToFriendsFromPeople([FromODataUri]string key) | ||
{ | ||
var entity = Api.People.FirstOrDefault(p => p.UserName == key); | ||
if (entity == null) | ||
{ | ||
return NotFound(); | ||
} | ||
|
||
var friends = entity.Friends; | ||
if (friends == null) | ||
{ | ||
return NotFound(); | ||
} | ||
|
||
var serviceRootUri = Helpers.GetServiceRootUri(Request); | ||
IList<Uri> uris = new List<Uri>(); | ||
foreach (var friend in friends) | ||
{ | ||
uris.Add(new Uri(string.Format("{0}/People('{1}')", serviceRootUri, friend.UserName))); | ||
} | ||
|
||
return Ok(uris); | ||
} | ||
|
||
[HttpGet] | ||
[ODataRoute("People({key})/Friends({key2})/$ref")] | ||
public IHttpActionResult GetRefToOneFriendFromPeople([FromODataUri]string key, [FromODataUri]string key2) | ||
{ | ||
var entity = Api.People.FirstOrDefault(p => p.UserName == key); | ||
if (entity == null) | ||
{ | ||
return NotFound(); | ||
} | ||
|
||
var friends = entity.Friends; | ||
if (friends == null) | ||
{ | ||
return NotFound(); | ||
} | ||
|
||
var serviceRootUri = Helpers.GetServiceRootUri(Request); | ||
if (friends.All(t => t.UserName != key2)) | ||
{ | ||
return NotFound(); | ||
} | ||
|
||
return Ok(new Uri(string.Format("{0}/People('{1}')", serviceRootUri, key2))); | ||
} | ||
|
||
[HttpPost] | ||
[ODataRoute("People({key})/Friends/$ref")] | ||
public IHttpActionResult CreateRefForFriendsToPeople([FromODataUri]string key, [FromBody] Uri link) | ||
{ | ||
var entity = Api.People.FirstOrDefault(p => p.UserName == key); | ||
if (entity == null) | ||
{ | ||
return NotFound(); | ||
} | ||
|
||
var relatedKey = Helpers.GetKeyFromUri<string>(Request, link); | ||
var friend = Api.People.SingleOrDefault(t => t.UserName == relatedKey); | ||
if (friend == null) | ||
{ | ||
return NotFound(); | ||
} | ||
|
||
entity.Friends.Add(friend); | ||
return StatusCode(HttpStatusCode.NoContent); | ||
} | ||
|
||
[HttpDelete] | ||
[ODataRoute("People({key})/Friends({relatedKey})/$ref")] | ||
public IHttpActionResult DeleteRefToFriendsFromPeople([FromODataUri]string key, [FromODataUri]string relatedKey) | ||
{ | ||
var entity = Api.People.FirstOrDefault(p => p.UserName == key); | ||
if (entity == null) | ||
{ | ||
return NotFound(); | ||
} | ||
|
||
var friend = entity.Friends.SingleOrDefault(t => t.UserName == relatedKey); | ||
if (friend == null) | ||
{ | ||
return NotFound(); | ||
} | ||
|
||
entity.Friends.Remove(friend); | ||
return StatusCode(HttpStatusCode.NoContent); | ||
} | ||
|
||
[HttpGet] | ||
[ODataRoute("People({key})/BestFriend/$ref")] | ||
public IHttpActionResult GetRefToBestFriendFromPeople([FromODataUri]string key) | ||
{ | ||
var entity = Api.People.FirstOrDefault(p => p.UserName == key); | ||
if (entity == null) | ||
{ | ||
return NotFound(); | ||
} | ||
|
||
var friend = entity.BestFriend; | ||
if (friend == null) | ||
{ | ||
return NotFound(); | ||
} | ||
|
||
var serviceRootUri = Helpers.GetServiceRootUri(Request); | ||
var uri = new Uri(string.Format("{0}/People('{1}')", serviceRootUri, friend.UserName)); | ||
return Ok(uri); | ||
} | ||
|
||
[HttpPut] | ||
[ODataRoute("People({key})/BestFriend/$ref")] | ||
public IHttpActionResult CreateRefForBestFriendToPeople([FromODataUri]string key, [FromBody] Uri link) | ||
{ | ||
var entity = Api.People.FirstOrDefault(p => p.UserName == key); | ||
if (entity == null) | ||
{ | ||
return NotFound(); | ||
} | ||
|
||
var relatedKey = Helpers.GetKeyFromUri<string>(Request, link); | ||
var friend = Api.People.SingleOrDefault(t => t.UserName == relatedKey); | ||
if (friend == null) | ||
{ | ||
return NotFound(); | ||
} | ||
|
||
entity.BestFriend = friend; | ||
return StatusCode(HttpStatusCode.NoContent); | ||
} | ||
|
||
[HttpDelete] | ||
[ODataRoute("People({key})/BestFriend/$ref")] | ||
public IHttpActionResult DeleteRefToBestFriendFromPeople([FromODataUri]string key) | ||
{ | ||
var entity = Api.People.FirstOrDefault(p => p.UserName == key); | ||
if (entity == null) | ||
{ | ||
return NotFound(); | ||
} | ||
|
||
entity.BestFriend = null; | ||
return StatusCode(HttpStatusCode.NoContent); | ||
} | ||
} | ||
} |
53 changes: 0 additions & 53 deletions
53
...aEndToEnd/Microsoft.OData.Service.Sample.TrippinInMemory/Controllers/TrippinController.cs
This file was deleted.
Oops, something went wrong.
126 changes: 126 additions & 0 deletions
126
test/ODataEndToEnd/Microsoft.OData.Service.Sample.TrippinInMemory/Helpers.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. See License.txt in the project root for license information. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Globalization; | ||
using System.Linq; | ||
using System.Net.Http; | ||
using System.Text.RegularExpressions; | ||
using System.Web; | ||
using System.Web.Http.Routing; | ||
using System.Web.OData.Extensions; | ||
using System.Web.OData.Routing; | ||
using Microsoft.OData.UriParser; | ||
|
||
namespace Microsoft.OData.Service.Sample.TrippinInMemory | ||
{ | ||
public static class Helpers | ||
{ | ||
public static TKey GetKeyFromUri<TKey>(HttpRequestMessage request, Uri uri) | ||
{ | ||
if (uri == null) | ||
{ | ||
throw new ArgumentNullException("uri"); | ||
} | ||
|
||
string serviceRoot = GetServiceRootUri(request); | ||
uri = RebuildUri(uri, serviceRoot); | ||
var pathHandler = (IODataPathHandler)request.GetRequestContainer().GetService(typeof(IODataPathHandler)); | ||
var odataPath = pathHandler.Parse(serviceRoot, uri.LocalPath, request.GetRequestContainer()); | ||
|
||
var keySegment = odataPath.Segments.OfType<KeySegment>().FirstOrDefault(); | ||
if (keySegment == null) | ||
{ | ||
throw new InvalidOperationException("The link does not contain a key."); | ||
} | ||
|
||
var value = keySegment.Keys.FirstOrDefault().Value; | ||
return (TKey)value; | ||
} | ||
|
||
public static string GetSessionIdFromString(string str) | ||
{ | ||
var match = Regex.Match(str, @"/\(S\((\w+)\)\)"); | ||
if (match.Success) | ||
{ | ||
return match.Groups[1].Value; | ||
} | ||
|
||
return default(string); | ||
} | ||
|
||
public static string GetServiceRootUri(HttpRequestMessage request) | ||
{ | ||
var urlHelper = request.GetUrlHelper() ?? new UrlHelper(request); | ||
var pathHandler = (IODataPathHandler)request.GetRequestContainer().GetService(typeof(IODataPathHandler)); | ||
string serviceRoot = urlHelper.CreateODataLink( | ||
request.ODataProperties().RouteName, | ||
pathHandler, new List<ODataPathSegment>()); | ||
return serviceRoot; | ||
} | ||
|
||
public static Uri RebuildUri(Uri original, string serviceRoot) | ||
{ | ||
var serviceRootSessionId = GetSessionIdFromString(serviceRoot); | ||
if (serviceRootSessionId == null) | ||
{ | ||
throw new ArgumentNullException("Key in request URI is null."); | ||
} | ||
|
||
var originalSessionId = GetSessionIdFromString(original.ToString()); | ||
if (originalSessionId == null) | ||
{ | ||
var uri = default(Uri); | ||
var builder = new UriBuilder(original.Scheme, original.Host, original.Port, | ||
HttpContext.Current.Request.ApplicationPath); | ||
var beforeSessionSegement = new Uri(builder.ToString(), UriKind.Absolute).AbsoluteUri; | ||
var afterSessionSegment = original.AbsoluteUri.Substring(beforeSessionSegement.Length); | ||
|
||
var sessionSegment = string.Format("(S({0}))", HttpContext.Current.Session.SessionID); | ||
var path = CombineUriPaths(beforeSessionSegement, sessionSegment); | ||
path = CombineUriPaths(path, afterSessionSegment); | ||
uri = new Uri(path); | ||
|
||
var uriBuilder = new UriBuilder(uri); | ||
var baseAddressUri = new Uri(serviceRoot, UriKind.Absolute); | ||
uriBuilder.Host = baseAddressUri.Host; | ||
uri = new Uri(uriBuilder.ToString()); | ||
|
||
return uri; | ||
} | ||
|
||
if (originalSessionId.Equals(serviceRootSessionId)) | ||
{ | ||
return original; | ||
} | ||
|
||
throw new InvalidOperationException( | ||
String.Format( | ||
CultureInfo.InvariantCulture, | ||
"Key '{0}' in request is not the same with that '{1}' in service root URI.", | ||
originalSessionId, | ||
serviceRootSessionId)); | ||
} | ||
|
||
private static string CombineUriPaths(string path1, string path2) | ||
{ | ||
if (path1.EndsWith("/", StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
if (path2.StartsWith("/", StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
path2 = path2.Substring(1); | ||
} | ||
} | ||
else | ||
{ | ||
if (!path2.StartsWith("/", StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
path2 = "/" + path2; | ||
} | ||
} | ||
|
||
return path1 + path2; | ||
} | ||
} | ||
} |
Oops, something went wrong.