Valence user search returns 404 - desire2learn

The call executed is …/users/
with parameter orgDefinedId = “e5555555”.
As per documentation, an array of UserData should be returned.
In practice, when such user doesn’t exist, the call returns 404 "Resource Not Found" (not documented).

This is a documentation oversight. The answer is:
If you used the action with no query parameter filters, the action returns a paged result set containing the users it can find. If, because of the calling user's role permissions, the action can find no users, it returns with a 200 status code, but an empty result set.
If you used the action with a query parameter filter (userName or orgDefinedId), the action returns the matching user record(s) it can find; if it can find no matching user(s), the action returns with a 404 status code.
The documentation has been updated to clarify this.

Related

How can I get an exception thrown when a user mis-types the name of a querystring PM of data type string?

I'm using MVC 3 and vs2010 and VB.NET.
I'm using 'HandleError' on my controller which works nice and easy and automatically detects an unhandled exception and redirects the user to an error page of my choice. However, there's a problem.
Here's an example of an action method I'm using:
<HandleError>
Public Function ReportAProblem(DespatchNoteNo As String, DespatchNoteItemId As Long) As ActionResult
Dim uiview As New PickingReportAProblemVM(DespatchNoteNo, DespatchNoteItemId)
' Get the data for ReportAProblem
GetDataForReportAProblem(uiview)
Return View(uiview)
End Function
When the user manipulates the URL in the following ways, an exception is thrown automatically and the user is redirected to my error page:
.../?DespatchNoteNo=DN1234&DespatchNoteItemId=A (incorrect data type for DespatchNoteItemId)
.../?DespatchNoteNo=DN1234&DespatchNoteItem=1 (incorrect parametername for DespatchNoteItemId)
An exception seems to be thrown automatically (please correct me if I'm wrong) which is picked up by HandleError and the user is redirected to my error page.
However, if the user types the following:
.../?DespatchNote=DN1234&DespatchNoteItemId=1 (incorrect parameter name for DespatchNote)
It seems that there's no exception thrown (please correct me if I'm wrong) and the user is not redirected to my error page, but instead the code just continues.
As far as I can see when I'm debugging, when the action method is called, in all scenarios described above the value of the parameter is set to Nothing.
Again, the difference seems to be that for any parameters of a type OTHER than String an exception is thrown APART FROM parameters of type String where this doesn't seem to be the case.
I'm obviously checking the contents of the variable again later on in the service layer of my application but in the above scenario (i.e. the user has been manipulating the querystring and should have his/her fingers chopped off) I don't want the code to get into the service layer at all but instead have the user redirected to my error page (just like what's happening for non-string data types).
Does anyone know of a way to get an exception thrown if the user manipulates the name of a String type querystring parameter? Or am I going around this the wrong way?
Most likely this is because the DispatchNoteNo variable is a string. Since it is not provided in the URL, it is now an empty string. No exception will be thrown here. So you have a few options.
Check for String.IsNullOrEmpty(DispatchNoteNo) in your controller, redirect if true.
Use routing to your advantage -> create a route with these values. If one is missing, the route will fail. An example is at the end because I fail at syntax markup this morning...
Here, if one or both of the parameters is not defined or if someone removes one of the route constraints, this route will not match the request. As long as you do not have a route it will match further down, the server will return a 'No route matched the supplied blah blah blah' (sorry, don't remember the exact wording of this) error
routes.MapRoute("Dispatches",
"Controller/ReportAProblem/{DispatchNoteNo}/{DespatchNoteItemId}",
new { controller = "Controller", action = "ReportAProblem" }
);
Here's the workaround I've come up with.
It's not perfect as I still need 1 line of code for each String type parameter I want to check in an action method, but if that's the closest to perfect I'll accept it.
I've created the following actionfilter:
Public Class CheckStringParam
Inherits ActionFilterAttribute
Public Property Parameter As String
Public Property InputValue As String
Public Overloads Overrides Sub OnActionExecuting(filterContext As ActionExecutingContext)
If Parameter <> String.Empty AndAlso filterContext.ActionParameters.ContainsKey(Parameter) Then
If filterContext.ActionParameters.TryGetValue(Parameter, InputValue) Then
If InputValue Is Nothing Then
Throw (New ArgumentException)
End If
End If
End If
End Sub
End Class
It's basically called with a parameter name. If you've supplied a parameter name and it exists within the context of the action, it will try to get its value. If that succeeds it checks if it is set to Nothing. If so, it throws an exception. This will then automatically be picked up by "HandleError" and the user gets redirected to the user screen.
The action method now looks like this:
<CheckStringParam(Parameter:="DespatchNoteNo")>
<HandleError>
Public Function ReportAProblem(DespatchNoteNo As String, DespatchNoteItemId As Long) As ActionResult
Dim uiview As New PickingReportAProblemVM(DespatchNoteNo, DespatchNoteItemId)
' Get the data for ReportAProblem
GetDataForReportAProblem(uiview)
Return View(uiview)
End Function
There's no other code needed and it will result in the user getting redirected if he/she does manipulate the URL and types in an incorrect parameter name.
I'm interested to hear what people think.

Non-existant content in MVC application - what to return to visitor/user?

Suppose we have implemented our routes to support URLs as such
/content/5
/news/10
or maybe we even use slugs. Regardless of what we use as our content identifier, what should the user be returned for non-existant content?
For instance, user requests /news/10 and our controller has this code:
public virtual ActionResult Display(int id, string slug)
{
return View(_repository.Find(id));
}
The above will most likely result in an exception when Find() returns null.
What are our options to jump in there and try to solve this issue?
do if..then check in controller action and direct user to some default page (maybe the entire content list if such a list and view exist),
return custom (friendly) 500 result (actually place custom HTTP error handling, so 500 will always redirect to custom friendly page),
return custom (friendly) 404 result (similar to option 2 but indicate that the content does not exist)?
We could interpret the error both as being the internal application error or as content not found error. Which one do you think is better to choose?
The same goes for administration pages - what to do there? In this case, I am much more inclined to actually redirect the user to the dashboard or list of content.
Please share your thoughts
I would create a view like NewsNotFound and if your repository returns null, return View("NewsNotFound", id); or something similar to that.
You could also do some logging at that point.
For a completely invalid controller/url, just handle that as a regular 404.
How we handle it is that we have three separate views; two views are taken care of by the error handling in the framework (the 404 and 500).
The NoContent view is one that we create outside of HandleError (or having the error handling in the global.asax.cs, and we normally have a check in our controller for null or zero items in an IEnumerable<T> (as the case may be) and if that check is true, we return View("NoContent");

Checking for nulls in ASP.NET MVC Controllers

Another opinion question:
What is the proper (in your opinion) to check for nulls in an MVC controller. For instance, if you have an edit controller that fetches a record from the db based on an id, what do you do if that record is not found? I found this article, but I'm not sure I like that method. Do you just check for it with an if statement and redirect to a 404 page? What solution do you use?
I don't know if it's best practice, but I check with an if and redirect to a "NotFound" view that states "The company/client/whatever you requested does not exist or was deleted."
Did it this way simply b/c I followed the NerdDinner tutorial when setting up the skeleton of my site, and that's how they do it.
That's what I do in my blog:
public ActionResult DisplayPublication (int nr)
{
if (!PublicationExists (nr))
throw new (HttpException (404, ""));
// ....
return ...;
}
As a general rule of a thumb, if a resource is requested which does not in fact exist, return HTTP 404. Definitely not return 200 OK along with the message about the missing resource. If not found, should be 404. If you changed the structure of your urls, consider 301 Moved Permanently.
Depending on the type and logic of the software you're developing, you may decide to exercise a different reaction to that situation, it's up to you.
I use a method similar to the article you linked to: an action filter that returns a 404 if the view model is null. I've combined it with a custom action invoker (like this) so that I don't have to put the filter attribute on everything.
Since I mentioned it, there are several other types of actions you can do if you go the action filter route. I have/had filters that will:
Automatically redirect to the Index view after a successful edit.
Redirect to the same page if the ModelState is invalid.
Redirect to an access denied page if a security exception is thrown.
I'm thinking about refactoring these to a convention registry so I can have something like:
When.ModelIsNull.RedirectTo<SharedController>(c => c.NotFound());
For("Edit").ModelStateIsInvalid.Redisplay();
For("Edit").OnSuccess.RedirectTo("Index");
On<SecurityException>().RedirectTo<SharedController>(c => c.AccessDenied());
Then if I wanted to change how a particular behavior works I just change it in one place. For example, instead of going to Index, I could redirect to the View view.
For("Edit").OnSuccess.RedirectTo("View");
I hope this gives you some ideas.
Edit: Here is how to could accomplish something similar using FubuMVC (which I love to steal ideas from)

Grails controller methods

Many of the available controller methods (chain, forward, redirect) take a map which can include keys such as:
id
params
model
A couple of questions about these:
Is 'id' just an alias for a request parameter named 'id'? In other words, is there any difference between:
chain(controller: "member", action: "showProfile", params: [id: memberId])
and
chain(controller: "member", action: "showProfile", id: memberId)
The chain method (possibly among others) allows passing a model and/or params (map) from controller action A to B. Practically speaking, what's the difference between passing data from action A to B via the params and model maps? Also, if the data is passed in the model map, how do I access it in controller action B?
Everything Burt said is correct. In addition, the reason that you'd want do do a chain (if you have a model) or a redirect (if you don't have a model to keep) is because both of those methods return a 302 redirect response to the browser. The browser then knows to ask for the next page.
It then has the correct url in the header for the resulting page, rather than the url from the page where the original request was from.
This pattern is very useful after a POST of information as it avoids all kinds of trouble with bookmarking, and resubmitting of information if the user hits refresh on the resulting page.
Ex: if you're saving a Book and you want to render the list page if the book is successfully saved. If you just call "controller.list()" in your method, it will show the user the list of books that gets rendered, but the url bar will still say ".../book/save". This is not good for bookmarking or reloading. Instead, calling redirect/chain will send the 302 response to the browser telling it to ask for the ".../book/list" page, which it does. All of your variables (your model and other flash messages) are in flash scope so they're still available to your model/view to use and everything is happy in the world.
This pattern is called Post/Redirect/Get.
'id' comes from UrlMappings entries such as "/$controller/$action?/$id?" - see http://docs.grails.org/latest/guide/single.html#urlmappings for usage.
Params are querystring parameters or form post parameters, accessed in non-Grails apps using "request.getParameter('foo')" but simplified in Grails as "params.foo". The contents of the model map are stored in the Request as attributes, accessed in non-Grails apps using "request.getAttribute('foo')" but simplified in Grails as "request.foo" or more typically accessed directly in GSPs, e.g. "${foo}".

ActionResult return to page that called it

I have a ActionLink, that calls my public ActionResult, and I would like it to return back to the page that it was called from, but how?
There are a couple of tricks that you can use for this.
The simplest is ...
return Redirect(HttpContext.Request.UrlReferrer.AbsoluteUri);
AbsoluteUri may not give you the exact path you are looking for, but UrlReferrer should have the imformation you are looking for. Redirect returns a subclass of ActionResult so it is a valid return value.
Another idea is to base the redirect location off of stored values. This is useful when you are going to make multiple requests before you want to redirect, such as when you validate a form and show validation issues on the first response. Another situation will be when the referrer is not a local site. In either case, your referrer won't be what you want it to and you will need to retrieve the correct location from somewhere else.
Specific implementations include using a hidden input field on your form, session state, pulling a descriminator value from your route data, or even just a more constant value like HttpContext.Request.ApplicationPath.
Good luck.
Keep in mind that due to the state-less nature of the web, your ActionResult isn't "called from" your ActionLink as much it is simply a url that the user-agent requested.
Because of this, the only real "built-in" way you can know where that user was coming from is by inspecting the http Request headers to see what the referring page was:
string referrer = Request.Headers["referer"];
You'd then be responsible for parsing out the Action method from this url, if you were going to call it directly. Be aware that this referrer may not be a link within your own site.

Resources