using falcor for a multi parameter request with transient data - falcor

I'm having trouble getting my head around how to use Falcor for a particular use case.
Basically I need to take a few fields from a page and execute server side validation business logic. The page should just display whether the validation was successful or not and if not, the reason.
I could technically use a falcor get query, but they don't seem suited to multi-parameter calls
I could try and use a Falcor 'call', which would allow me to easily pass through multiple parameters, but is not suited to returning transient data.
Is this just a use case that Falcor should not really be used for or am I missing something?

All the data returned by a Falcor server is part of the model, transient or not.
A get is appropriate here because you want to read data. call are appropriate to make black box modifications to the model.
gets are always multi-parameters because you give the entire path of the data which can enclose whatever you want. Let's say we want to validate a URL. We could do something like:
getValue('updateProfileForm.website["http://example.com"].valid')
And that would return true of false depending on the URL. The result can be kept in cache eternally since it will never change (a URL is either always valid or it is not).
If the validation process needs to know the value of multiple fields at once, like password confirmation, you can do something like this:
getValue('updateProfileForm.password["new password"].confirm["new password"].valid')
If the validation depends on something external to the form, like what time it is, include this parameter in the path to maximize cache-ability.

Related

How to limit properties bound when using domain model as a command object

This really powerful feature of grails
def save(MyDomain model) {
model.save()
render ''
}
will parse the request body or params, run MyDomain.get(id), fill in the properties from the request body or params and save. That's a lot for this little bit of code.
How do I limit the properties to bind to model? Say I have an accountBalance property that is read only and I don't want a malicious user to be able to change their account balance.
Also, I want to have multiple actions that save a different subset of properties of MyDomain... say one action could be for a bank teller user that is making a deposit for the account holder. In this case the teller should be able to set accountBalance but not password.
I realize that an actual banking app wouldn't work like this, it's just an example.
I had other problems that led me to use command objects to bind data (see Grails fails to parse request when content type is specified during post). Any solution would also have to address that post. I imagine if the solution uses command objects then it will work, but if command objects aren't in the solution, then the request body problem has to be addressed.
Have not tried on an actual domain class but can you try using bindData instead of implicitly binding where you can particularly specify which property to exclude?
def save() {
//params - A Map of source parameters
//It can be params or any other representation of request body
//request.JSON, request.XML
MyDomain model = MyDomain.get(params.id?.toLong())
bindData(model, params, [exclude: ['accountBalance']])
model.save()
render ''
}
I suggest you take a look at the documentation about binding. There is a lot of information, in particular the section about security which is similar to your concerns. Looking at the fact bindData() allows you include/exclude properties you should be able to write any variation of your binding you need.

Desire2Learn Valence API, PUT CourseOffering 404

Based on the information here http://docs.valence.desire2learn.com/res/course.html#actions I would expect that to 'update' a courseOffering I would specify a PUT with a CourseOfferingInfo block, which only contains a few attributes. Every time I try this, I get a 404, not found - even using the same route for a successful GET (404 says org doesn't exist OR org is not an offering - neither is true). However, if I specify a CreateCourseOffering block (directly from a previous GET), the PUT works fine. Is this correct and the documentation not? Or are there other things I should look for in this scenario? The documentation says use CreateCourseOffering for the POST to create an offering… I simply want to update one attribute of that offering and as such thought the PUT was the way to go.
If you use the "create" POST route with a CreateCourseOffering block, this will create a new course offering, and send back the CourseOffering block for the newly created course offering (this will include the org unit ID value for the new org unit you've built).
If you want to update an existing course offering, you should, as you suspected, use the "update" PUT route with a CourseOfferingInfo block. Note that you must provide valid information for all the fields in this block, since when used successfully, the LMS will use all the properties you specify in that block for new values for the org unit. The StartDate and EndDate fields are particularly finicky: you must provide either a valid UTCDateTime value (notice that the three-digit millisecond specifier in these values is mandatory) or a JSON null value if the field is not applicable.
Why a 404? What you're seeing with the 404s and the data you're passing is likely down to the way the back-end service is doing data binding. It tries to de-serialize your provided JSON data (and query parameters) into data objects it can read/manipulate -- if you provide a JSON block that contains a superset of the properties it's expecting, then this may work (for example, if you provide a CourseOffering block when you're expected to provide a CourseOfferingInfo) as the binding layer may ignore fields it doesn't need. If the binding process fails, because you provide a value for a property that can't be bound to the data type expected, or because you fail to provide a JSON property field it expects, then this can cause the service to return a 404 (because binding/de-serializing incoming parameterized data happens at the same time as matching the URL route to an underlying service handler).
If you provide a JSON structure (and query parameters) that the web-service can bind to its expected data objects, but the values you provide are invalid or nonsensical, then this can cause the underlying service handler to respond with a 400 (signalling an Invalid Request). But in order to get this far, your parameterized data still needs to get properly deserialized and bound into data objects for the underlying service to examine.
We'll be updating the documentation to more explicitly draw out this fact. The safest policy from the calling client perspective is to pass valid JSON structures that are exactly what's expected by the individual routes, especially since the underlying back-end service implementation might change how it handles incoming requests.

How do I maintain a specific query string across all requests?

If someone goes to our website with a query string key of ref (for example mysite.com/AboutUs?ref=Test), is it possible to maintain that query string on all future links/form posts?
So for example, I may have a link on our website to go to mysite.com/Products. I would want this to be translated into mysite.com/Products?ref=Test.
Ideally I want to know if this is possible to do by inspecting the previous URL and adding it to the current URL when the request for the page is made, maybe by intercepting the route and appending the key (if it doesn't exist already).
The project is an MVC 4 application.
You could actually pass it along by adding it to every single URL, but that would require manually adding to each use of Html.ActionLink, etc. (or I suppose you could create a custom HTML Helper to do that for you, but then every developer who works on your project would need to remember to always use the custom helper), as well as all redirects and such in your controller actions. Long and short, this would be very time consuming and very fragile.
Your best bet is to simply intercept the initial request with the querystring parameter and then set a session var. Then, you can simply check for the presence of the session var instead of the querystring parameter.
To handle all this logic, your best bet is to create a global action filter. There's pretty extensive documentation on Filters at MSDN. Once you create your filter, you just have to register it in FilterConfig.cs (in App_Start) to make it global.
Set the URL parameter in a cookie, and later in your code do whatever you want to do based on presence of that value in either the cookie or URL.
if(parameter set in cookie OR URL)
// do stuff
if(parameter set in URL)
// set the cookie so that future actions are also tagged with that parameter
Alternatively if you want such tagging to happen only for the session, set a session variable.
To do it in the way you suggested - You could rewrite all links on your page based on this tag, but that would be a roundabout, and costly, way of doing this. Most languages allow a hook that allows your code to process the HTML output before it is sent out to browser; just run a appropriate regex search and replace to get what you want. e.g. PHP has ob buffering and associated functions. You could use the equivalent for .Net.

OpenRasta URI and method binding clarification - RESTful webservice

I'm using Openrasta for my RESTful webservice and I've a small doubt with regards to the method parameters and URI
For example: I've following Setup for user entity.
Configuration:
ResourceSpace.Has.ResourcesOfType<User>()
.AtUri("/user")
.And.AtUri("/user/{userId}")
.HandledBy<UserHandler>()
.AsJsonDataContract()
.And.AsXmlDataContract();
Handler method for PUT:
public OperationResult Put(long userId, User user){}
URI for the same will be http://localhost/User/1
Request body will contain a JSON as below:
{
"userId":1,
"userName":"FirstName"
}
Here, my question is: Defining the PUT method with two parameters is correct or not? If it is right way to do that, then userId parameter in the PUT method will contain same value as User entity property UserId.
And, in the PUT method I need to verify whether these two values are same or not and if they are not same I return BadRequest stating that URI doesn't match with the entity provided in request. Why should we do this explicitly why not it can be handled while processing the request and have PUT method take only User entity as parameter? Am I missing anything drastically or is my understanding about this design completely wrong? Any thoughts or opinions please?
There's a few reasons for it.
First, it's a technical limitation of how URI parameters are processed and matched to inputs one variable at a time. The same gets applied to key/values codecs, so that ought to let you have one User object. but when you use a json codec, we get back a full object, so that would end up overriding User alltogether.
The second one is that I never tried to fix that problem, mostly because combining uri parameters and response bodies leads to a whole bunch of hidden security issues you probably want to stay well clear of.
Last and not least, from a modeling perspective a ReST API ought to use URIs as identifiers and links instead of foreign keys, so if you already have your identifier (the URI), there's little reason why that should be modeled in your entity body.

Redirect After Post in ASP.NET MVC

I am using the Redirect After Post pattern in my ASP.NET MVC application. I have
the following scenario:
User goes to /controller/index where he is asked to fill a form.
Form values are POSTed to /controller/calculate.
The Calculate action performs calculation based on input and instantiates a complex object containing the results of the operation. This object is stored in TempData and user is redirected to /controller/result.
/controller/result retrieves the result from TempData and renders them to the user.
The problem with this approach is that if the user hits F5 while viewing the results in /controller/result the page can no longer be rendered as TempData has been expired and the result object is no longer available.
This behavior is not desired by the users. One possible solution would be instead of redirecting after the POST, just rendering the results view. Now if the user hits F5 he gets a browser dialog asking if he wants to repost the form. This also was not desired.
One possible solution I thought of was to serialize the result object and passing it in the URL before redirecting but AFAIK there are some limitations in the length of a GET request and if the object gets pretty big I might hit this limitation (especially if base64 encoded).
Another possibility would be to use the Session object instead of TempData to persist the results. But before implementing this solution I would like to know if there's a better way of doing it.
UPDATE:
Further investigating the issue I found out that if I re-put the result object in TempData inside the /controller/result action it actually works:
public ActionResult Result()
{
var result = TempData["result"];
TempData["result"] = result;
return View(result);
}
But this feels kind of dirty. Could there be any side effects with this approach (such as switching to out-of-process session providers as currently I use InProc)?
Store it in the Session with some unique key and pass the key as part of the url. Then as long as the session is alive they can use the back/forward button to their heart's content and still have the URL respond properly. Alternatively, you could use the ASP cache, but I'd normally reserve that for objects that are shared among users. Of course, if you used the parameters to the calculation as the key and you found the result in the cache, you could simply re-use it.
I think redirect after post makes much more sense when the resulting Url is meaningfull.
In your case it would mean that all data required for the calculation is in the Url of /controller/result.
/controller/calculate would not do the calculation but /controller/result.
If you can get this done thinks get pretty easy: You hash the values required for the calculation and use it as the key for the cache. If the user refreshes he only hits the cache.
If you cant have a meaningfull url you could post to /controller/index. If the user hits F5 calculation would start again, but a cache with the hash as key would help again.
TempData is generally considered useful for passing messages back to the user not for storing working entities (a user refresh will nuke the contents of TempData).
I don't know of more appropriate place than the session to store this kind of information. I think the general idea is keep session as small as possible though. Personally I usually write some wrappers to add and remove specific objects to session. Cleaning them up manually where possible.
Alternatively you can store in a database in which you purge stale items on a regular basis.
I might adopt a similar idea to a lot of banks on their online banking sites by using one-time keys to verify all POSTs. You can integrate it into a html helper for forms and into your service layer (for example) for verification.
Let's say that you only want to post any instance of a form once. Add a guid to the form. If the form does not post back and the data is committed then you want to invalidate the guid and redirect to the GET action. If say the form was not valid, when the page posts back you need a new (valid) guid there in the form waiting for the next post attempt.
GUIDs are generated as required and added to a table in your DB. As they are invalidated (by POSTS, whether successful or not) they are flagged in the table. You may want to trim the table at 100 rows.. or 1000, depending on how heavy your app will be and how many rendered but not yet posted forms you may have at any one time.
I haven't really fine tuned this design but i think it might work. It wont be as smelly as the TempData and you can still adhere to the PRG pattern.
Remember, with PRG you dont want to send the new data to the GET action in a temp variable of some sort. You want to query it back from the data store, where it's now committed to.
As Michael stated, TempData has a single purpose -> store an object for one trip only and only one trip. As I understand it, TempData is essentially using the same Session object as you might use but it will automatically remove the object from the session on the next trip.
Stick with Session imho rather than push back in to TempData.

Resources