I am building MVC application and would like to put caching in my application. I have read about caching that you need to just put [OutputCache(Duration=60, VaryByParam="none")] above controller method and it will work. However in my case i would like to cache not for whole controller methods but inner methods which would call from index controller and which will return IEnumerable<SelectListItem> and that result i want to cache.
But caching is only work for controller methods which will result view result, i have also searched for caching for non view methods and found some MVCDonutCaching and read this articles and by installing tried this also as per below
[DonutOutputCache(Duration=60, VaryByParam="none")]
public IEnumerable<SelectListItem> GetRegionList()
{
Region region = new Region();
return region.GetRegionsList();
}
But not luck to achieve my goal! have anyone done this type of caching here? then please help me to achieve this things.
Thanks in Advance.
I believe your problem is not with mvc itself but with caching model data. Caching your controller action is like forming static page and saving it in IIS cache. Every time user asks for the "Home/Index" (for example), the IIS takes well-formed page (html) from cache without executing any code.
What you're trying to do is cache model data. That's quite a different thing since it has nothing to do with IIS and html page forming. You could use existing solutions like:
Unity Application Block - http://msdn.microsoft.com/en-us/library/ff649102.aspx
Or this post from stackexchange: https://softwareengineering.stackexchange.com/questions/35709/recommendations-for-a-net-distributed-caching-framework
Related
In Sails.js, a route is set up against a controller method which can render a view. For the most part, this is straightforward, i.e. you could set up a GET /users route that points to UserController.find (which is usually set up automatically anyway).
However, say the home page of a blog renders the 10 most recent posts in the main section and a column with a list of authors and categories. The controller method has to fetch posts, authors, and categories before rendering the view and sending it back to the client. Clearly, a method like this doesn't really belong in PostController, AuthorController, or CategoryController.
What's the best thing to do in this situation? Create a controller for rendering views that rely on data from multiple models? Is there a good name for such a controller?
Thanks!
What I would do (this is purely opinion-based) is creating a PageController and create an action for each page you'd want.
For your home page example you can create a home action, get whatever you need and then render it with res.ok() (if everything is fine).
Another option would be to use Sails as a pure API and use HTTP requests (Ajax) or sockets to get your data in JSON. If you want to do so, I'd advise you to use a front end framework such as Angular, Ember, React...
By the way you could also create actions rendering HTML in your existing controllers and create a route to hit them through Ajax requests and just print them in your page. I'd prefer the 2nd solution because it takes full advantage of the Blueprint API (you don't need new controller or action whatsoever).
As Yann pointed out, this answer has to be a little opinionated. It seems that you are using the views system and not building a single page application. For the home page, I would go for an IndexController.js file with a home(req, res) action.
// api/controllers/IndexController.js
module.exports = {
home: function (req, res) {
// Retrieve all the information you need
// Take care about managing the asynchronous calls before rendering the view
return res.view('homepage');
}
};
Declare the route
// config/routes.js
module.exports.routes = {
'get /': 'IndexController.home'
}
Create the view in views/homepage.ejs.
I would develop my CakePHP application in the most reusable way. I'd like to treat it as webservices, so I don't want to strictly bind controller with view. My idea is: controller just returns json info, the view calls the controller and get the json and make html output.
How can I realize that? Could be a good approch, developing pages rather than views, and inside that pages call the webservices previously developed.
You can even forget about creating view files, using $this->set('_serialize', array('people')); in your PeopleController::show()
Well Cake is kinda' works like this "out of the box". You can use Router::parseExtensions(); to define what type of data you would like to serve. For example in app/Config/routes.php:
Router::parseExtensions('xml','json');
This will make it possible to detect what kind of request is incoming. For example if someone requests:
www.example.com/people/list.json or www.example.com/people/list.xml, in your PeopleController's list() method you'd be able to detect what kind of resource is being requested - json or xml, or of course any other
extension you define. This is what the RequestHandlerComponent is used for. You can check if it is xml for example:
if($this->RequestHandler->isXml()) {
//Some code
}
The different extensions are only different representation of the data, so it shouldn't matter what exactly you're serving. From v2.1 Cake will automatically switch the view class when it sees a JSON or XML request, which takes us to the new JSON and XML views.
All you will have to do is provide the views in the appropriate places.
In View/People (as for this example) you would have:
..View/People/
list.ctp
xml/
list.ctp - XML view
json/
list.ctp - JSON view
I have a Post class:
public class Post
{
...
public virtual IList<Comment> Comments { get; set; }
...
}
In mappings I set Comments as a ManyToOne reference. As we know by default it's set as lazy loaded.
In my Razor view script I want to check if post has any comment and if so, add a button that calls an action to get comments for that post via ajax and show them, by injecting html.
When I try to invoke something on Post.Comments in Razor (like Model.Comments.Count()) I recieve an exception saying that Session is not present. I know why that happens - because the lazy loading.
My question is how to handle these kind of situations? What are the 'best practices'?
Two solutions comes to my mind:
1) Set Comments as not lazy loaded - not ok since I get comments via ajax later and for this time I need only the Count of comments
2) Create a ViewModel class that contains information if post has comments or pass this via ViewBag.
What are your suggestions on this?
Thanks,
Bartek
Personally, I would go with option 2.
Create a ViewModel, include a property like HasComments and use that in your view instead of trying to evaluate Model.Comments.Count().
Why is your session ending so early?
You should keep it open still during render, for times like that.
A bit of context: I need to cache the homepage of my CakePHP site - apart from one small part, which displays events local to the user based on their IP address.
You can obviously use the <cake:nocache> tag to dictate a part of the page that shouldn't be cached; but you can't surround a controller-set variable with these tags to make it dynamic. Once a page is cached, that's it for the controller action, as far as I know.
What you can usefully surround with the nocache tags are elements and helpers. As such, I've created an element inside these tags, which calls a helper function to access the model and get the appropriate data. To get at the model from the helper I'm using:
$this->Modelname =& ClassRegistry::init("Modelname");
This seems to me, however, to be a kind of iffy way of doing things, both in terms of CakePHP and general MVC principles. So my question is, is this an appropriate way of getting what I want to do done, or should it ring warning bells? Is there a much better way of achieving my objectives that I'm just missing here?
Rather than using a Helper, try to put your code in an element and use requestAction inside of the element.
see this link
http://bakery.cakephp.org/articles/gwoo/2007/04/12/creating-reusable-elements-with-requestaction
This would be a much better approach than trying to use a model in your helper.
Other than breaking all the carefully-laid principles of MVC?
In addition to putting this item into an element, why not fetch it with a trivial bit of ajax?
Put the call in its own controller action, such that the destination URL -> /controller/action (quite convenient!)
Pass the IP back to that action for use in the find call
Set the ajax update callback to target within the element with the results of the call accordingly
No need to muck around calling Models directly from Views, and no need to bog things down with requestAction. :)
HTH
I want to use Wicket to build an application, but I have some designers that would like to write/maintain the javascript, and they basically expect 1 JS-segment per page, and a global JS-file.
I think the most natural way to add javascript in wicket is to add it per component (not per page), which would create problems for those designers (fractioned javascript, and having to write it in java-files). Is there a better way to solve this?
(of course, I expect things to work after a partial refresh.)
And a second (related) thing they'd like (and I'd like actually) is the possibility to request information in JSON-format through a static link , is this possible in Wicket?
I started with JSON by making my wicket pages return the JSON, but quickly realized there are better tools for the job, especially if you will have a full web services layer. If you just need a little JSON here and there, always via a GET, then sure, just make a Wicket page.
I ended up using Jersey with Jackson alongside of Wicket. Jersey simplifies the configuration of URLs that can do different things with different http methods (GET/POST/PUT/DELETE), as well as easily parsing query strings, etc. I'd consider going this route for heavier JSON needs.
You can easily run both Wicket and Jersey in the same web application with a little web.xml configuration.
Wicket's built in AJAX support is always stateful and thus accessed with changing URLs. If your designers aren't planning to use Wicket's JS library, it's pretty straightforward to mount a JSON page:
public class JsonReturningPage extends WebPage {
public JsonReturningPage(PageParameters params) {
String json = "{foo: 4711}";
IRequestTarget t = new StringRequestTarget("application/json", "UTF-8", json);
getRequestCycle().setRequestTarget(t);
}
}
Alternatively, you could also implement your own AbstractRequestTargetUrlCodingStrategy to directly return an IRequestTarget from IRequestTarget decode(RequestParameters params) and mount it in your application.
Regarding JS files, I'd try to educate them to use one file per component. This certainly has the advantage of less copy-paste code and simpler maitenance. Additionally, I'd certainly discourage JS in Java code. It's normally only needed to pass data or config to JS , either as variable definitions or method calls. As this data is typically in Java and JS is written by designers, it's time for designers and programmers to team up.
Quick answer to your second question is yes it is possible. Use bookmarkable links to access a resource that returns JSON data.
You can easily use the following code to dynamically communicate with Wicket:
AbstractDefaultAjaxBehavior callme = new AbstractDefaultAjaxBehavior(){
#Override
protected void respond(AjaxRequestTarget target) {
}
};
page.add(callme);
//From any ajaxrequesttarget you can simply append the following code:
target.appendJavascript("wicketAjaxGet('"+callme.getCallbackUrl()+");");
This way you can have an ajaxlink etc... that will transfer the ajaxrequest to the Wicket side. If you want to pass data (though a static link doesn't sound like that) do the following:
"wicketAjaxGet('"+callme.getCallbackUrl()+"&x='+value_to_pass_back''";
//to Read the value in the respond:
String x = RequestCycle.get().getRequest().getParameter("x");
So the url to the callback is dynamically generated (as the callback url is specific to the session) but it is formed like any other url....
To me this is 10 times simpler than building a JSON system on top of wicket instead of using the one built into it.... I use this all the time and it works great for me at least. If your solution is different/better I would like to know why perhaps.