Do you know any "best practice" to design a REST method to alter the order of a small collection?
I have a collection exposed at "GET /api/v1/items". This endpoint returns a JSON array and every item has a unique id.
I was thinking on create "PATCH /api/v1/items" and send an array of ids with the new order. But I wonder if there is any alternative or design pattern to accomplish this task properly.
Following the REST Uniform Interface constraint, the HTTP PUT and PATCH methods have to stick to the standard semantics, so you can do that with either one in the following way:
With PUT, clients can upload a whole new representation with the order they want. They will request GET /api/v1/items, change the order as they need, and submit it back with PUT /api/v1/items.
With PATCH, clients can send a diff document which performs the order change as they need. You can use a format like json-patch and clients perform the change with the move operation and array paths.
Be aware that neither of these are design patterns or best practices. They are simply how the PUT and PATCH methods are supposed to work. Ideally, this should work on any RESTful application implementing the GET, PUT and PATCH methods correctly for the resource at that URI, and that's the beauty of REST. If you do it the right way, you only have to do it once and clients can generalize for everyone. For instance, a client can choose to do it the PUT way with small collections, and the PATCH way for larger ones.
Both your idea to use PATCH with an id array, and the answerfrom #dit suggesting to do it with PUT aren't really RESTful because they are breaking up with the standard semantics: yours for not using a delta format, his for doing partial updates with PUT. However, both those options can be RESTful if done with POST. POST is the method to go for any action that isn't standardized by the HTTP protocol, so you can do anything you want with it, but you have to document how exactly to do it.
So, it's up to you. If you are concerned at all with being RESTful and your application has long term goals -- I'm talking years or even decades -- I'd say to go for a uniform implementation of the PUT and PATCH methods as suggested first. If you prefer a simple approach, use yours or dit's idea with POST.
ok, I had a similar problem and will try to explain how I solved it.
my bike tour has about 5 stations. Every station has an unique ID and order number:
stations": [
{
"uid": 1,
"order": 1
},
{
"uid": 2,
"order": 2
},
{
"uid": 3,
"order": 3
},
{
"uid": 4,
"order": 4
},
{
"uid": 5,
"order": 5
}
]
Every time if the order of single item was changed (drag and drop) i send REST request to my webservice.
Suppose we want to move the station uid=3 one position down. Station with uid=3 goes down and station with uid=4 goes up. So my PUT request looks like this:
...myapplication.com/api/changeorder?station=3&direction=down
Now, on the server side I just have to find items affected by this move down action and update their order in my database. My REST webservice sends OK if update was successful.
In my case it was not necessary to send the new sorted list, cause my UI was always changed by drag and drop action.
Since I was not going to promote changes in the current API, I have used PUT method.
I was implementing a reordering of entities called "Slider". dotnet core
public class SliderMoveDto
{
public MoveDirection MoveDirection { get; set; }
public int CurrentSequence { get; set; }
}
public enum MoveDirection
{
Down = 0,
Up = 1
}
Implementation:
public async Task UpdateAsync(SliderMoveDto sliderMoveDto, int sliderId)
{
var allSliders = (await _sliderRepository.GetAsync(null, col => col.OrderBy(s => s.Sequence))).ToList<Slider>();
int currentIndexOfSliderInList = allSliders.FindIndex(s => s.Sequence == sliderMoveDto.CurrentSequence);
int indexToSwap = sliderMoveDto.MoveDirection == MoveDirection.Up
? currentIndexOfSliderInList-1
: currentIndexOfSliderInList+1;
SwapItems<Slider>(allSliders, currentIndexOfSliderInList, indexToSwap);
await RecalculateOrderOfSliders(allSliders);
}
Auxiliary methods:
public static void SwapItems<T>(IList<T> list, int indexA, int indexB)
{
T tmp = list[indexA];
list[indexA] = list[indexB];
list[indexB] = tmp;
}
private async Task RecalculateOrderOfSliders(List<Slider> allSliders)
{
for (int index = 0; index < allSliders.Count; index++)
{
int idOfSlider = allSliders[index].Id;
var sliderToUpdate = await _sliderRepository.GetByIdAsync(idOfSlider);
sliderToUpdate.Sequence = index + 1;
_sliderRepository.Update(sliderToUpdate);
}
await _unitOfWork.CommitAsync();
}
Related
I have read this post and the theory I think that is clear. I have a DAL that only has the methods to add, get, update and delete information in a database.
So I guess that I have an application in which I have clients, orders and type of client. Type of client has a percent that set the discount to make to a type of client.
The business layer request to DAL the type of client to know the discount.
The business layer create the order with the price and apply the discount according to the type of client.
The business layer send to the DAL the command to add the new order, sending the new order.
In code I can have this:
DAL:
public async getClientType(long paramIDClientType)
{
using(Entities myDbContext = new Entities())
{
return await myDbContext.ClientTypes.Where(x=> x.IDType == paramIDClientType).SingleOrDefault();
}
}
public async addOrder(Orders paramNewOrder)
{
using(Entities myDbContext = new Entities())
{
myDbContext.Orders.Local.Add(paramNewOrder);
await myDbContext.SaveChangesAsync();
}
}
Business layer:
public void addOrderToClient(CLients paramClient)
{
ClientTypes myType = myDAL.getClientType(paramClient.IDClient);
ORder myNewOrder = myNewOder();
myNewOrder.IDClient = paramClientIdCLient;
myNewOder.Amount = 300;
myNewOrder.Discount = myType.Discount;
myNewOder.Total = nyNewOrder.Total - myNewOder.Amount * myNewOder.Discount;
myDAL.AddOrder(nyNewOrder);
}
But I have a problem with the concurrency in this case, because I want to ensure that I use the correct discount, so I want to avoid the discount of a type of client is changed by another user un the middle of the process of add the new order.
If I use optimistic concurrency, I have to have a timestamp column in my ClientTypes table, but this not solve my problem, because in the addOrder method in my DAL layer, I only pass as parameter the new order, so the method don't have the timestamp value that has the business layer to check if the type of the client has changed to ensure that the discount used is the correct.
SO I am thinking in this solution:
public async addOrder(Orders paramNewOrder)
{
using(Entities myDbContext = new Entities())
{
string sql = "select ct.* from ClientTypes as ct, CLients as c"
+ " where ct.IdType = c.IdType and c.IdType = " + paramNewOrder.IdCLient;
ClientTypes myClientType = await myDbContext.CLientTypeSqlQuery<CLientTypes>(sql).SingleOrDefaultAsync();
if(paramNewOrder.Discount != myCLientType)
{
throw new Exception("Discount incorrect.");
}
paramNewOrder.Total = paramNewOrder.Amount - paramNewOrder.Amount * myClientType.Discount;
myDbContext.Orders.Local.Add(paramNewOrder);
await myDbContext.SaveChangesAsync();
}
}
This is my business layer, but use EF to get the data, so I think that this solution merge DAL abd business layer. Is this true? If this is true, I guess that is a not good solution. But then, how could I control concurrency?
Thanks.
Yes, optimistic concurrency control doesn't help you to prevent inserting a faulty new order, because you don't commit the ClientType. Only updating a ClientType would raise an exception if the discount was changed in the mean time.
But carefully consider the requirements. Is it really of paramount importance that the correct discount is used milliseconds after it's modified? If so, you have to look for a locking mechanism. Otherwise, just fetch the current discount at the very last moment, do the calculation and commit the order.
You could implement a locking/calculation/insert mechanism in a stored procedure that is mapped to the insert action of an Order. EF can map CUD actions to stored procedures..
I'm trying to understand RxJava and I'm sure this question is a nonsense... I have this code using RxJava:
public Observable<T> getData(int id) {
if (dataAlreadyLoaded()) {
return Observable.create(new Observable.OnSubscribe<T>(){
T data = getDataFromMemory(id);
subscriber.onNext(data);
});
}
return Observable.create(new Observable.OnSubscribe<T>(){
#Override
public void call(Subscriber<? super String> subscriber) {
T data = getDataFromRemoteService(id);
subscriber.onNext(data);
}
});
}
And, for instance, I could use it this way:
Action1<String> action = new Action<String>() {
#Override
public void call(String s) {
//Do something with s
}
};
getData(3).subscribe(action);
and this another with callback that implements Runnable:
public void getData(int id, MyClassRunnable callback) {
if (dataAlreadyLoaded()) {
T data = getDataFromMemory(id);
callback.setData(data);
callback.run();
} else {
T data = getDataFromRemoteService(id);
callback.setData(data);
callback.run();
}
}
And I would use it this way:
getData(3, new MyClassRunnable()); //Do something in run method
Which are the differences? Why is the first one better?
The question is not about the framework itself but the paradigm. I'm trying to understand the use cases of reactive.
I appreciate any help. Thanks.
First of all, your RxJava version is much more complex than it needs to be. Here's a much simpler version:
public Observable<T> getData(int id) {
return Observable.fromCallable(() ->
dataAlreadyLoaded() ? getDataFromMemory(id) : getDataFromRemoteService(id)
);
}
Regardless, the problem you present is so trivial that there is no discernible difference between the two solutions. It's like asking which one is better for assigning integer values - var = var + 1 or var++. In this particular case they are identical, but when using assignment there are many more possibilities (adding values other than one, subtracting, multiplying, dividing, taking into account other variables, etc).
So what is it you can do with reactive? I like the summary on reactivex's website:
Easily create event streams or data streams. For a single piece of data this isn't so important, but when you have a stream of data the paradigm makes a lot more sense.
Compose and transform streams with query-like operators. In your above example there are no operators and a single stream. Operators let you transform data in handy ways, and combining multiple callbacks is much harder than combining multiple Observables.
Subscribe to any observable stream to perform side effects. You're only listening to a single event. Reactive is well-suited for listening to multiple events. It's also great for things like error handling - you can create a long sequence of events, but any errors are forwarded to the eventual subscriber.
Let's look at a more concrete with an example that has more intrigue: validating an email and password. You've got two text fields and a button. You want the button to become enabled once there is a email (let's say .*#.*) and password (of at least 8 characters) entered.
I've got two Observables that represent whatever the user has currently entered into the text fields:
Observable<String> email = /* you figure this out */;
Observable<String> password = /* and this, too */;
For validating each input, I can map the input String to true or false.
Observable<Boolean> validEmail = email.map(str -> str.matches(".*#.*"));
Observable<Boolean> validPw = password.map(str -> str.length() >= 8);
Then I can combine them to determine if I should enable the button or not:
Observable.combineLatest(validEmail, validPw, (b1, b2) -> b1 && b2)
.subscribe(enableButton -> /* enable button based on bool */);
Now, every time the user types something new into either text field, the button's state gets updated. I've setup the logic so that the button just reacts to the state of the text fields.
This simple example doesn't show it all, but it shows how things get a lot more interesting after you get past a simple subscription. Obviously, you can do this without the reactive paradigm, but it's simpler with reactive operators.
I'm trying to understand how to work with TableController in Azure Mobile Apps. Here's the sample TodoItemController:
public class TodoItemController : TableController<TodoItem>
{
protected override void Initialize(HttpControllerContext controllerContext)
{
base.Initialize(controllerContext);
MobileServiceContext context = new MobileServiceContext();
DomainManager = new EntityDomainManager<TodoItem>(context, Request, Services);
}
// GET tables/TodoItem
public IQueryable<TodoItem> GetAllTodoItems()
{
return Query();
}
// GET tables/TodoItem/48D68C86-6EA6-4C25-AA33-223FC9A27959
public SingleResult<TodoItem> GetTodoItem(string id)
{
return Lookup(id);
}
// PATCH tables/TodoItem/48D68C86-6EA6-4C25-AA33-223FC9A27959
public Task<TodoItem> PatchTodoItem(string id, Delta<TodoItem> patch)
{
return UpdateAsync(id, patch);
}
// POST tables/TodoItem
public async Task<IHttpActionResult> PostTodoItem(TodoItem item)
{
TodoItem current = await InsertAsync(item);
return CreatedAtRoute("Tables", new { id = current.Id }, current);
}
// DELETE tables/TodoItem/48D68C86-6EA6-4C25-AA33-223FC9A27959
public Task DeleteTodoItem(string id)
{
return DeleteAsync(id);
}
}
Ideally, I'd like to avoid passing around whole models like TodoItem to reduce incoming/outgoing bandwidth and limit clients to only what they should care about. If I were to do that, how would offline sync and client-side SDKs be affected?
Is TableController intended for simple CRUD operations as suggested above? Any examples out on the Internet with complex queries?
The Mobile Apps TableController is the basis for an OData based CRUD interface. You will always transmit an entire model (which is based on an EntityData model, so it has four additional fields - version, createdAt, updatedAt and deleted) to the client. However, the client can use an OData search to get a specific set of entities. For more information on OData, check out http://www.odata.org/
In the specific case of Offline Sync and using the Mobile Apps SDK for clients, the client SDK will issue a GET but limit the results to the last update time (which will be zero for the first request and hence will get everything). It will then push up the changes from the client. In certain cases (where the version does not match), it will have to do conflict resolution. Check out "How Offline Sync Works" in their documentation: https://azure.microsoft.com/en-us/documentation/articles/app-service-mobile-offline-data-sync-preview/
I'm just starting to work with ServiceStack.Redis. I can put individual key/values into the cache and get them from the cache. However, I can't seem to get all items or a count of the items in the cache.
Here's the code
using (RedisClient cacheClient = new RedisClient(cacheServer))
{
IRedisTypedClient<CustomerEntity> customerCache = cacheClient.As<CustomerEntity>();
customer = bl.FetchCustomer(customerId);
//cache for two minutes
customerCache.SetEntry(customerId, customer, new TimeSpan(0, 2, 0));
//These all show the count as 0
logger.Debug(customerCache.GetAll().Count);
logger.Debug(cacheClient.GetAll<CustomerEntity>().Count);
var customers = customerCache.GetAll();
logger.Debug("{0} customers in the cache", customers.Count);
}
In your CustomerEntity class:
(e.g)
public string strManufacturer;
should be replaced as
public string strManufacturer { get; set; }
I guess redis can't access when the getter and the setter is not explicitly defined.
I was unable to store my C# objects in redis, this modification fixed the issue for me.
I was getting output
"{}"
in redis-cli when I "get" the key before making this modification and GetAll().Count was returning 0 as in your situation.
You should also pay attention of license terms of ServiceStack.Redis if you're going to use it in a production environment. See here for the discussion on SO.
Wondering how some of the more experienced (or anyone with a better idea than I have) would tackle my particular modeling scenario...
I have a typical "Category -> SubCategory ->TertiarySubCategory" scenario and I'm not sure if I'm mapping it out correctly. I am mapping this directly to an MVC route since raven seems to lend itself well with this. Under the final category (which can be at the first, 2nd or 3rd levels there will be a list of items associated with only that level of a category. So, we might have something like:
Single level category: '/Politics/'
Second level category: 'Politics/People' or 'Politics/Websites'
Tri-Level Category: 'Sports/Pro/Volleyball' or 'Sports/College/Football'
In a traditional RDBMS this is easy through primary/foreign keys + a few joins... so, wondering how I would handle with Raven?
From what I have read should I store the entire 'sports/pro/volleyball' URI or Key in a list of items that fall under it?
i.e. -
public class CategoryItem
{
public string FriendlyName {get;set;} // Volleyball or Pro Volleyball
public string CategoryURI {get;set;} // i.e. - "/sports/pro/volleyball/"
public string content {get;set;} // i.e. - "Who is the best Pro Volleyball Athlete?"
public List<string> Comments {get;set;}
}
// then we could store something like this:
var survey1 = new CategoryItem();
survey1.CategoryURI = "/sports/pro/volleyball/"
survey1.Content = "Who is the best female pro volleyball player?";
survey1.Comments.Add(new Comment("Misty May"));
var survey2 = new CategoryItem();
survey2.CategoryURI = "/sports/pro/volleyball/";
survey2.Content = "Who is the best male pro volleyball player?";
survey2.Comments.Add(new Comment("Some guy I don't kow");
// asuumes ravenSession was alreadyopened...
ravenSession.Store(survey1);
ravenSession.Store(survey2);
ravenSessoin.SaveChanges();
//{ ...... etc ..... }
//Then I can query by CategoryURI without needing joins (denormalization).... i.e. -
var items = session.Query<CategoryItem>()
.Where(x => x.CategoryURI == "/sports/pro/volleyball/");
Or should I create a List items member of the actual category class? Each item would have a list of it's own comments... meaning everything's stored in a single document within Raven - i.e. -
public class Category
{
public string FriendlyName {get;set;} // i.e. - "Volleyball" or "Pro Volleyball"
public string URI {get;set;} // i.e. - "/sports/pro/volleyball" which is the MVC path
public List<CategoryItem> Items {get;set;}
}
public class CategoryItem
{
public string Content {get;set;}
public List<string> Comments {get;set;}
}
var vballCat = new Category();
vballCat.FriendlyName = "Pro Volleyball";
vballCat.URI = "/sports/pro/volleyball/"; // equivalent to the MVC route
var catItem = new CategoryItem().
catItem.Content = "Who is the best male pro volleyball player?";
catItem.Comments.Add("Misty May");
catItem.Comments.Add("Some Guy 1");
vballCat.Items.Add(catItem);
ravenSession.Store(vballCat);
ravenSession.SaveChanges();
..... now once I pull the primary cat i.e. - "/sports/pro/volleyball/" I have everything I need already under it
var items = session.Query<Category>()
.Where(x => x.URI == "/sports/pro/volleyball/");
{ ............. etc ............... }
Now here I can just iterate through the Items collection and it's collection of comments.... does this use eager loading? What if I had a million comments under one category item? When I load the main category would it load all one million comments too!?!?
I would appreciate any help you can provide. Sorry if this example/question is unclear... I'll try to clarify anything if you guys need it. Thanks again!
The answer is that it depends on the size of your data and your usage scenario.
The first example is useful if you have large number of items and want to access categories without its items.
The second example is useful if you usually access category with its items, and the size of items is limited (note that limited is still high, several thousands wouldn't cause me to blink).
Note that there is no such thing as eager / lazy loading in RavenDB, you are talking about a single document vs. multiple documents, not about relations between documents. The entire document is loaded when you need it.
Another thing to remember is that it is usually faster to query by id than querying. That means that if you have ids that already looks very much like Document Ids, you might as well MAKE them the document ids.