ServiceStack View/Template control when exception occurs? - templates

I added some razor views and use a request filter to check browser version and switch between desktop and mobile views. But when a exception occurs, especially validation exception, it seems the framework return immediately and never touched any custom code. I tried request/response filter, service exception handler, none got executed. It seems to ignore view/template specified in URL query string as well.
Is there way to set view/template during exception? Thanks

The first question is how are you handling validation exceptions?
the most common procedure to perform this kind of task is by using the fluentValidation, the response can return a message for more than one validation at the time, all the validations are against DTOs and you´ll need to implement an AbstractValidator, the first thing you need to do is to register the validators that belons to your applciation like the following:
Plugins.Add(new ValidationFeature());
container.RegisterValidators(typeof(CredentialsAuthValidator).Assembly);
I´m valdiating in this case that the Auth username and password should not be Empty, take a look to the following example:
public class CredentialsAuthValidator : AbstractValidator<ServiceStack.ServiceInterface.Auth.Auth>
{
public CredentialsAuthValidator()
{
RuleSet(ApplyTo.Post, () =>
{
RuleFor(x => x.UserName).NotNull().WithMessage("Username Required").When(x => x.provider == "Credentials");
RuleFor(x => x.Password).NotNull().WithMessage("Password Required").When(x => x.provider == "Credentials");
}
);
}
}
if some of the validation fails you´ll get a responseStatus from the server with the errorCode and the messages.
You can configure a custom httpHandlers in the case you would like to have a handler for specific scenarios or a global error handler, this can be performed in your serviceHost configuration, something like this:
GlobalHtmlErrorHttpHandler = new RazorHandler("/views/error"),
CustomHttpHandlers =
{
{HttpStatusCode.NotFound, new RazorHandler("/views/notfound")},
{HttpStatusCode.Unauthorized, new RazorHandler("/views/login")},
{HttpStatusCode.Forbidden, new RazorHandler("/views/forbidden")},
}

Thanks for the help from Pedro, and especially mythz from ServiceStack. Now I think I start to understand my problems.
ServiceStack is first and foremost a service framework and Razor is just another view over the same result. But I was a little hesitate with a full on client side solution and keep falling back to familiar territory and looking for some kind of code-behind feature. That seems to be the root of lots of my struggles.
After some more research, this is what I come up so far.
ServiceStack for service, of course.
Razor view to build the basic layout and the main page for each major feature
Build a json script tag from model to hold initial data, like in SS's HTML Report
Jquery and Eldarion ajax for all subsequent in-page processing
Handlebars for javascript templating
Verifyjs for validation
So far look promising. Pages are lot smaller in size, running super smooth and mostly pure json flying over the wire.
Still a work in progress, all suggestions welcome.

ViewSwitch works when I changed to use Request Filter instead. Got the correct layout and all the references, etc. Although they have to share the same error page, but there's not much formatting in there.

Related

In Ember automatically route application to error route if template promise returns error

Given a route it is easy enough to get Ember to navigate to an error route if the model promise rejects. Currently I have the simple method of having an error.hbs and /routes/error.js, and if the model promise errors it loads the error page.
I have a situation where the model resolves fine, but one of its relationships does not. This relationship is used in the routes template e.g.
{{#each model.addresses as |address id|}}
{{address.line1}}
{{/each}}
So myurl.com/api/addresses/1 returns a 500 error. I see this in the console window, but Ember does not automatically transition to the error page. How can I get it to do this for all promises that reject as a result of a template requesting more data?
One solution would be to return RSVP.Promise in route model() which loads all data (also relationships instead of lazy loading them later by template) and rejects if any of asynchronous requests fail.
Ember generates the error pages by it self if im not wrong, if ember depends on an DS.error object for the transition you have to fulfill the requirements in order to get Ember to recognize an valid error, in Ember 2.x the error code MUST be 422 and has to follow jsonapi http://jsonapi.org/format/#errors-processing
I wrote up a long post on using Route error substates here -> https://pixelhandler.com/posts/emberjs-handling-failure-using-route-error-substates
So ultimately, error handling happens as the result of knowing "what broke" and "who owns the fact that it broke". Generally, if X asked for Y and Y fails, its X's job to display the error. In that example, if FooRoute triggers an ajax, and it fails, FooRoute more or less should handle the error.
But when it comes to the template causing fetches, it actually becomes the responsibility of the template.
One thing one can do is, actually bind to the various boolean properties representing the async operation on the PromiseProxy (in your case, model.addresses). The properties are as follows
isPending - ongoing work is happening
isFulfilled - it is done, and succeeded
isRejected - it is done, but failed
isSettled, - it is done (failed or succeeded)
using these flags could be as follows
{{#if model.addresses.isPending}}
loading...
{{else if mode.addresses.isRejected}}
Sorry something went wrong, {{model.addresses.reason.message}}
{{else}}
{{#each model.addresses as |address| }}
...
{{/each}}
{{/if}}
When loading data for a page, I like to ask myself, what data is critical to show? That is, if there are three sections on the page -- say backed by foo, foo.bars, and foo.baz -- are all three sections of highest priority? Or can I let one of them fail and show the other two? Let's assume that without either foo or foo.bars, we show an error page, but foo.baz is optional. In that case, I would write that as
// controller:foo
model(params) {
return this.get('store').find('foo', params.id);
},
afterModel(foo) {
return foo.get('bars'); // block on foo.bars fetch
}
Then I might have a {{foo-baz}} component that renders Loading... at first, then fetches foo.baz in the background and shows the full content later.

Loading bar that tracks completed HTTP requests for Ember.js

I've been looking around, and short of writing a basic one myself, I couldn't find a library that already exists for Ember that displays a small loading line at the top of the page that completes when all the http requests have completed for a page transition (whether that be images loading, JSON being fetched etc).
There's this for Angular: http://chieffancypants.github.io/angular-loading-bar/, but wondering if Ember has any options already.
Cheers.
EDIT: I've found this article as well about a jQuery plugin, which I imagine could be adapted: http://tutorialzine.com/2013/09/quick-tip-progress-bar/. Still keen on hearing if anyone knows of anything already integrated into the Ember request lifecycle though.
You can use fantastic javascript component NProgress (http://ricostacruz.com/nprogress)
and then you can initialize it in Application.ready event using jQuery like this
window.App.ready = function () {
$(document).ajaxStart(function () {
NProgress.start();
});
$(document).ajaxStop(function () {
NProgress.done();
});
};

How to handle 404 of Ember Data in route?

In my route I have a method that tries to request a list of models from the server
model: ->
App.MyModel.find
projectId: (#modelFor "project").id
Now obviously sometimes this might return a 404.
At the moment when this happens, Ember just stops doing anything. No view is rendered, no controller is setup.
So how can I properly handle the 404 (ie show an error view)?
Bad news: right now, ember-data doesn't do anything when it gets a 404 on find(). At all. The model sits in the 'loading' state forever.
There are no non-completely-stupid options, here, in my opinion. What I would probably do as a last resort is add a notFound attribute on my DS.Model, and instead of returning 404, return JSON with notFound set to true. It's painful, I know...
--- I had originally offered a solution of overriding find in a subclass of RESTAdapter. Then I noticed that find DOES NOT get passed the record instance it is supposedly loading. So, no go on handling 404s by putting the record into an error state.
[NOTE: ember-data has changed dramatically since March 2013, the information in this answer may no longer be operative]
Incidentally, the "new" BasicAdapter was just released now. The question for me was, will this make things easier to handle 404 errors.
Approach #1
My first approach - similar to what Christopher was suggesting - was to add an additional field containing the HTTP status.
status: DS.attr("number");
And then I used this AJAX call:
$.getJSON(url, data).then(null, function(xhr) {
return {
id: id,
statusCode: xhr.status
};
}).always(function(data) {
return process(data).load();
});
What this does is to transform the error response (xhr) to a hash containing the requested id and the status code. Finally, the successful result or the failed hash are passed to the store.
This kind of works, but isn't very practical: When you show a list of all model instances those "mock" instances have to be filtered out manually.
Approach #2
Another idea was to create a special error model.
App.Error = App.Model.extend({
status: DS.attr("number")
});
And the according query:
$.getJSON(url, data).then(null, function(xhr) {
return App.store.load(App.Error, {}, {
id: 0,
status: xhr.status
});
}).done(function(data) {
return process(data).load();
});
This will load and create a new instance of the error model and put it into the store.
The problem with this is that Ember wasn't really "accepting" this. The application just stopped routing, doing nothing anymore. So this seems like a dead end as well :(
I hit this issue as well today.
However, after looking at the source, it appears the model is actually setup to utilize Ember.Evented, and we can add our own handlers for these cases.
The two events that caught my eye were becameError and didLoad.
In my case I was able to do something like the following:
// Grab a user by id.
var user_rec = App.User.find( user.id );
// Oh no! Error!
user_rec.on('becameError', function() {
alert('I could not find you!');
});
// We should be good! Proceed!
user_rec.on('didLoad', function() {
alert('Your email: '+this.get('email'));
});
Here's the source on github: https://github.com/emberjs/data/blob/master/packages/ember-data/lib/system/model/model.js
Hopefully, if this is indeed the way we should be handling things, there will be some added documentation in the guides in the near future.

Proper procedure for using sproutcore-routing

Curious about the proper procedure, or at least common procedure for using sproutcore-routing.
In the read me there it shows this basic example for routing:
SC.routes.add(':controller/:action/:id', MyApp, MyApp.route);
I'm assuming that in most cases MyApp.route would call the supplied action on the supplied controller. My question is more about beyond this step how you handle the setup/teardown stuff for an application where you have lots of primary views.
Are people instantiating new controllers when the controller changes as to always start with a clean slate of data and views? Or is it more common/advisable to instantiate all the controllers and such at load and simply use the routing to show/hide primary views?
I suppose the same question goes when bouncing between actions within a controller. Is it proper to do some teardown, especially on bindings/listeners, and then re-establishing them if the action is recalled?
My question may be a little fuzzy, but I'm basically wondering how people handle lots of primary views, and deal with cleanup so stuff doesn't get stale or chew up lots of resources.
I wrote a blog post that describes a method for this: http://codebrief.com/2012/02/anatomy-of-a-complex-ember-js-app-part-i-states-and-routes/
In most Ember and Sproutcore apps and examples I have seen, controllers are instantiated at app initialization. Routes drives state changes in statecharts, where controllers are updated and views are created/destroyed as needed.
I have the following setup.
in my Ember.Application.create() I have the following code:
MyApp.routes = Em.Object.create({
currentRoute: null,
gotoRoute: function(routeParams) {
console.log('MyApp.routes gotoRoute. type: ' + routeParams.type + ' action: ' + routeParams.action + " id: " + routeParams.id);
if (routeParams.type === 'expectedType' && routeParams.action === 'expectedAction' && routeParams.id) {
//find item with ID and load in controller
MyApp.MyController.findItemWithId(routeParams.id);
//Navigate to the correct state
MyApp.stateManager.goToState('stateName');
}
}
})
SC.routes.add(":action/:type/:id", MyApp.routes, 'gotoRoute');
Then, when I click on things that should cause the URL to change I do:
SC.routes.set("location", "show/item/ID-123-123");
Your app should now be listening to changes in the URL and cause the correct action to happen based on the URL-part.
You could probably move the MyApp.MyController.findItemWithId(routeParams.id); to the enter() function of the statechart (if you are using them), but you do need to store that ID somewhere in some controller.

Grails g:include tag to include controller call

I asked this question here I have a new grails app and the index page is made up of several partial templates. Each of my partial templates need to load data from a different controller, the suggested solution was to use the tag - I have tried this but seeing nothing happen, and having searched the web I cant find any fully functioning examples of this in action.
Here is my partial template _newsFeed.gsp:
<div id="news_feed">
<g:include controller="news" action="latestsNews" /></div>
and my controller NewsController.groovy:
class NewsController {
def latestsNews = {
println "in controller"
[news: "News Headline!"]
}
In the above example, Im just trying to confirm that the controller is being called (which is why the println is there) - but im never getting anything.
Can someone point me towards a working example or explain if i am missing something?
Thanks
I don't see anything major wrong with your code. You are missing a closing brace in your NewsController, but I suspect that was just a typo. I just tested the following:
class HomeController {
def showMessage = {
println "Showing message"
[message: 'this is a message']
}
}
showMessage.gsp just has ${message} in it. And then in my index.gsp
<g:include controller="home" action="showMessage" />
I get the correct response. Is everything else in your view rendering correctly, are you sure the page with the includes is actually getting called/rendered?
When invoking http://localhost:8080/myapp/home/showMessage can you see the log messages in your console ? Please make sure of that first.
The use of the tag is correct and I used it many times ago.
However the use of this tag is not recommended because you perform many controller calls for each request. You can use instead to render a template without invoking a second controller.