Accessing lazy loaded property in NHibernate ASP.NET MVC3 Razor code - asp.net-mvc-3

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.

Related

input validation not working on asp.net mvc 4 model sent as JSON

I have a model and a form in the view. I have a simple field of string which is called description. I'm able to insert scripts like: <script>alert('xss')</script> to that field.
I can see that in other actions on my site with other models I can't
I do not have an AllowHtml or anything like that.
the only difference is that for this model I use a post with a json object and content-type of application/json
the ModelState.IsValid is returning true. even though there is a description property with an xss script on it...
and for the other actions I make a simple ajax post.
why isn't the validation input work on this kind of JSON ajax posts?
how can I prevent xss across the entire site for this kind of ajax requests?
thanks
It is because ValidateInput is only for FormValueProvider. As for JsonValueProvider, you need to roll out your own mechanism.
Steps
1) Create a marker attribute CustomAntiXssAttribute
2) Create a custom model binder by sub-classing DefaultModelBinder
3) Overrides BindProperty method -> get the attempted value for the underlying property, sanitize it and assign it to the view model property.
Check this out.
Edited:
Replace the line var valueResult = bindingContext.ValueProvider.GetValue(propertyDescriptor.Name); with var valueResult = bindingContext.ValueProvider.GetValue((string.IsNullOrWhiteSpace(bindingContext.ModelName) ? string.Empty : bindingContext.ModelName + ".") + propertyDescriptor.Name); in order to support nested ViewModel.
try using AntiXssLibrary from Nuget, and by using getSafeHtmlContent. you can get the safe content while you're saving your records to db.
Another approach is to use a Sanitizer library like this one, you can choose which HTML tags you want to be filtered out.

Issue with caching for non view methods in MVC3

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

Hide url routing parameters in asp.net mvc

Is there a method for specifically hiding the routing parameters in ASP.NET MVC from the users. Specifically, I'd like a link
http://sitename.com/Do?title = 2
to simply become
http://sitename.com/Do
but internally pass the titleId to my controller.
Is that do able?
Thanks
Update: yes, there are buttons on my webpage that currently have such as their href, but I'd rather hide all the parameters so users dont go to other parts of the page directly by trying differnt parameters. #Moshe, no its not a from submit or post else I'd have used a strongly typed view. Thanks
As long as your parameters are on the client, they are never 'hidden' unless you encrypt them. You could store the parameter in a hidden field and set the action method to post, then the value is not visible in the URL. But a user with a little bit of knowlegde about web could still manipulate the hidden field (unless you encrypt the value in some way).
EDIT: If it has to be save you have to check the user's credentials on the server. Otherwise you can obscure the data like in the other sample or you can use encryption, e.g. with ProtectData.Protect(...).
For simple numeric values that have to be passed back and forth to a view you can write two private methods in your controller:
private int Obscure(int source) {
return (source*source) * 3; //or something clever you come up with
}
private int DeObscure(int obscuredValue) {
return (int)Math.Sqrt(obscuredValue / 3); //inverse the Obscure method
}
You can use these to obscure values before you pass them to a view, and de-obscure them after you get them posted back. Mind you, this is really not a good way to implement security, as is explained in this stackoverflow post.
Another option is to create an Obscure/DeObscure procedure that takes in the entire querystring and somehow mangles that back and forth. This would required writing a custom ViewEngine though. Sounds interesting...

Form from another model in a view

So I'm trying to extend the Blog tutorial adding some comments:
Post hasMany Comments
I want to display the add comment form in the same view as the 'post view'. Thing is I don't know the best way to get this approach. I thought about three ways:
Creating a function in Comments Controller to handle the data.
Creating a function in Post Controller to handle the data.
Deal with the data in the same function that deals with the post views.
The main problem with the two first 'solutions' is that the validation errors doesn't show up in the form unless I do some messy hacking of saving the invalidated field in a session variable and then parsing the variable on the beforeFilter callback, like this:
function beforeFilter () {
if ($this->Session->check('comment_error')) {
$this->Post->Comment->validationErrors = $this->Session->read('comment_error');
$this->Session->delete('comment_error');
}
}
What I basically do is adapt the invalidated fields to the actual view and allow it to show properly. This works really well, but it seems so ugly to me. What would be the best approach?
Another related question: should a controller reflect a view? I mean on that example, I thought about only having a Comment Model and dealing with all the data in the controller where's the form to add a comment (even though it's in the Post Controller).
Sounds like you're looking for the Mutlivalidatable behaviour: http://bakery.cakephp.org/articles/dardosordi/2008/07/29/multivalidatablebehavior-using-many-validation-rulesets-per-model
This allows you to define more than 1 validation ruleset per model. Use your controller to determine which one to apply upon posting something.
P.S. I have only ever used this on a Cake 1.3 project, not sure if it'll work on 2.0.
I see it this way:
Under every post there is an input box "Add comment" with a button to submit.
After submitting some text a form redirects to comments_controller where the comment is saved with this post_id, body, author, date etc.
After the comment is saved and all the logic is done it takes you back to the post.
Under each post there are all related comments displayed (having the same post_id sorted by date or whatever).

Getting the url of an aspx page using the page type

I'm using a web application project.
I have a folder in my web root called Users and in the folder I have a page called UserList.aspx
What I want to be able to do is type in Response.Redirect(Users.UserList.URL)
What I reckon I can probably do is create a class that extends Page and add a static property called URL that calls MethodInfo.GetCurrentMethod().ReflectedType (I think this works haven't tested) and then have that convert Users.UserList -> ~/Users/UserList.aspx
The problems with this method that I know of are one I need to go through every page and make it extend the base class and it doesn't work with any pages that contain a '-' character.
The advantages are that if pages are moved around then there aren't any broken links (Resharper gives out when there is a Page with the wrong namespace).
Also then every individual page that takes query string params could have a static method so that if I want to add/remove params I can see what uses those params etc.
Also if I want to call that page I don't have to check the name of the params e.g. UserId userId, Id or id. So that would look something like Users.ViewUser.GetUrl(1) -> ~/Users/ViewUser.aspx?UserId=1
So the question is: Is there a better way of doing this? Or is this a bad idea in principal?
You could just create an extension method for the base Page class that does what you are thinking. That would avoid having to go back and modify the base class for all your pages.
There is a better way. Create a traffic cop that knows about paths. Then if paths change, your data model changes or other stuff you just change that one place. Plus you could have read from a config file and make changes at run time.
Thus your call looks like this:
Repose.Redirect(TrafficCop["Users.UserList"].URL)
or some other way if you don't like the syntax.
The MethodInfo.GetCurrentMethod().ReflectedType doesn't work so I came up with another method of doing this using generics.
Instead of Users.ViewUser.GetUrl() or Users.ViewUser.URL it's GetUrl()
For a page with parameters it's still Users.ViewUser.GetUrl(1), it isn't ideal because they should both have the same way of being called but better than strings I guess.
Going to leave the question open for a while just in case.
edidt: I think I will actually just create another method called GetUrl(String getQuery) because if I have two parameters that are of the same type it doesn't work very well.
further edit: I found out how to do exactly what I want to do.
created a class called BasePage:Page where T : Page
on that are the static methods redirect and geturl
each page inherits from the base page as follows: MyPage:BasePage
Any page can redirect to that page by using the command MyPage.Redirect();

Resources