So, There are multiple ways a client can pass values to server. Request Body, Header and/or Cookies.
On the server side these values could be retrieved by ModelBinders, ValueProviders MediaFormatters, FromBody, FromUri, Dependency Inject a component that reads it from current http Context or Read from current HTTP context directly ( I know this is the worst one for unit testing. So, never do that).
The question is how to decide which to be used for what.
What I think is for all the user input use ModelBinder. For anything else, like authentication token in header dont use the model binder but a authentication attribute. Which reads from the header or cookie.
What about the case where you have somthing like a cartId and you are updating the Items in cart, Shipping address, Payment address etc. Now, using DDD Cart must be the root object and Items, shipping address and payment must be the child and each request must receive a cart and the dependent object. But, that would be a really heavy load. So, why not to pass around only cartId and why not to store that cartId in cookie and if we do that. How should we read the value of cartId, use a ModelBinder, Dependency Inject a component that reads it from current http Context or Read from current HTTP context directly ( I know this is the worst one for unit testing. So, never do that)
So, any id that is not an auth token or a session token and is required in the action method. But it is not being passed as an input in request body or query strings. What is the best approach to read parameters like that
What about the case where you have somthing like a cartId and you are
updating the Items in cart, Shipping address, Payment address etc.
Now, using DDD Cart must be the root object and Items, shipping
address and payment must be the child and each request must receive a
cart and the dependent object.
Don't confuse DDD with HTTP/REST. DDD is for your domain. HTTP/REST is for your web resources.
Why not something like this?
add product to the cart
POST /my/carts/1/products { body/model: productId=6&quantity=2 }
update quantity
PUT /my/carts/1/products/6 {body/model: quantity=4 }
...and I have to argue with your DDD design. Shipping and billing addresses are really parts of the Order aggregate, not the Cart aggregate. But I digress...
If you organize your HTTP resources to mimic your DDD aggregates, then you don't need to pass the whole cart in with each request. You can have different user actions call different resources/method combinations to interact with the aggregate. You don't even need to send the cartId in with the body of the request, because it is already in the URL:
[POST("my/carts/{cartId:int}/products")]
public HttpResponseMessage PostProduct(int cartId, CartProductPostModel model)
{
// ensure user owns the cart (based on cookie or authentication info)
// get the cart aggregate based on the cartId,
// add the product to the cart
// tell the client you succeeded by passing back an appropriate response
// 201 Created
// Location: http://www.site.com/my/carts/1/products/6
// note the response does not send back the whole cart, it only tells you
// the new resource was created and where you can access it
}
If you design your HTTP resource URL's RESTfully, then you don't need to pass around any id's in headers, cookies, session, etc, because all of the information you need is already in the request -- either in the URL itself, or in the request body.
Update
So, in our case cartId is not an integer it is a string that actually
has some "/"s (IIS/ASP.net MVC blows up). I know weird but thats how
it is and I can't change it. So, it can't be there as part of url. It
could be part of a query-string. But, to make it inter operate with
someother clients. We are kind of forced to put it on cookie.
Yes you can put it in the URL. You just have to encode it first. So a cart ID like cart/with/slashes ends up like this in the URL:
add product to the cart
POST /my/carts/cart%2fwith%2fslashes/products
update quantity
PUT /my/carts/cart%2fwith%2fslashes/products/6
This will work just fine with either MVC or WebAPI routing without blowing up.
[POST("my/carts/{cartId}/products")]
public HttpResponseMessage PostProduct(string cartId, CartProductPostModel model)
{
// cartId will be "cart/with/slashes", decoded
}
Related
I have a callback_url that, by all accounts, lives in a vacuum. A third-party (Shopify) hits the URL, and with very strict constraints at that.
I have tried these but I cannot:
add params to the URL
control the headers/payload
utilize existing cookies (this isn't the user hitting the callback)
Really, I can't find anyway to get session data, or more specifically, a very crucial customer Id, to the callback_url. The callback_url is being used to send back user-specific data but that's not possible without some key indicator (customer ID)
Am I missing something simple or is this as much of a challenge as I thought? I feel like it's on an island.
I have a rest API for an application that I am developing. One of the endpoints receives the name, email and phone fields to create a new user (without password). Obviously the endpoint would be /users [POST]
Would it be correct to take advantage of this endpoint to, if the user already exists, update it with the new data? Or is it better to create a different endpoint (PUT) to update the user? If so I would have to put the business logic outside of this API, and I don't like that idea.
This question is not related to DDD, as DDD does not provide guidance on API design.
But to answer your question, whether or not you should use PUT or POST will depend on whether or not the action should be idempotent.
POST is typically used to create a new resource
POST is not idempotent, if the same request is sent multiple times there will be different results (new resource gets created each time). The same request sent to POST /users will create a new resource each time.
PUT is used to either create or replace an existing resource (not necessarily update).
The PUT method is idempotent, so if the same request is sent multiple times it will be the same as if it is sent once. The same request sent to PUT /users/1 will have the same result.
If you want to update part of the resource (update rather than replace), you can use PATCH.
I'm implementing a cart and currently using Zuora's Direct Post.
Basically it's a form submit to Zuora and upon success Zuora will redirect back to my site. They allow for 5 field_passthroughs which are just query string parameters in the url.
I have the flow working as such:
User enters in their Card Information
On Submit, information is submitted to Zuora
On Success, Zuora redirects back to my site, which lands on an intermediate processing page
Zuora sticks a few fields on the redirectURL such as paymentMethodId, which I use to place the order on the processing page.
I want to optimize it now so that instead of landing on the intermediate processing page, it'll just land back on the user's cart with the input fields still populated.
In order to achieve this without refetching fields like name/email from my backend, Is there a way I can pass it on the redirectUrl? Would it be safe to serialize my Vuex state into a string and encode it? Then when it lands back on my cart from the redirect, I decode and deserialize and repopulate the form?
You can pass some of that information back automatically.
Any of the fields in the HOP page configuration in Zuora where the "Returned in Response" checkbox are checked will return as querystring parameters. Email, phone, and address fields can be returned this way.
Unfortunately (Cardholder) Name is not one that can be checked. That would have to be passed back through one of the field_passthroughs. I would say yes about passing it that way as it would be using https and querystring values are already encrypted.
I am not an expert on security and some fields like CC numbers should never be passed ths way.
When a user changes a dropdown, I need to make an ajax call to an endpoint, that grabs the data and return it as a JSON.
I can do the event stuff with Vue, to make the request, but how do I guarantee that Vue is the requestor?
I can't really put an API key or something in the JS as that can be viewed through source. Someone could also watch the network tab in chrome and replay the requests to retrieve the data.
Unless you want to ask people to login first, there is no way you can do this. There is a HTTP header you can look for that most libraries add for Ajax requests, but that can be faked as well.
You cannot hide any information from the request you are making. It's the server side on which you can make your code strong. To prevent fake request you can use CSRF token, you need to also validate if the user is logged in, you can check session etc. before you send the result to the client.
I just tried to set up a new payment method, following the example here: https://hotcakescommerce.zendesk.com/hc/en-us/articles/204725899-Custom-Payment-Method-Example
However, I'm missing some next steps.
So it seems the 1st thing is redirect the customer to the payment provider in the ProcessCheckout method.
And it also seems that when the user is redirected back I can add some code to the Checkoutcontroller class, to do some updates on the order.
However, at some point, the payment provider will also do a server-to-server call, before the customer is sent back to the store website.
Is there some way/some place I can process that response too?
I also need to send the return url to the payment provider. Is there a good way to construct this url ?