I have been looking at C# MVC for a while now and really getting in to it. I have come across how to pass 2 or more Domain Models in to a View but what i need to ask is security. I have read about Over Posting and that is can be stopped with Binding inclusions and exclusions but how does this effect a ViewModel with 2 or more Model inside it. Is there still the possibility of hidden fields in the HTML that resolve to the Domain Models and are they editable.
I have been looking to make ViewModels where i give it certain things i want the user to edit but it just seems over complicated, so is there a better and easier way of doing this.
public TicketViewModel {
private Ticket _ticket;
public TicketViewModel(Ticket Ticket)
{
_ticket = Ticket;
}
public string Title
{
get
{
return _ticket.Title;
}
}
public List<Comment> Comments
{
get
{
return _ticket.Comments;
}
}
}
As you can see I create a new ViewModel with the Ticket Domain Model but the main concern that i have is returning a List of Domain Model Comments as i only want them to be read only.
Any help would be greatly appreciated.
For security:
If i get what you are asking about then
First of all the user can edit everything on the client side and we cannot do anything for this.
But for your concern if you have not added code on server side than no one will be able to change your data using your application , also you can add validation on server side.
For adding List in a ViewModel:
public class MainViewModel
{
public string Title{get;set;}
public List<Comment> ListComments {get;}
}
"i have is returning a List of Domain Model Comments as i only want them to be read only"
you can use this,
public List<Comment> Comments { get; }
Consider the ReadOnlyCollection, and the method AsReadOnly provided by List.
Your comment property can be rewritten as -
public List<Comment> Comments
{
get
{
return _ticket.Comments.AsReadOnly();
}
}
If you don't want something to be editable, just don't modify it.. I think this is unrelated to MVC.. You are in control of server code, so if you want comments to be readonly, just don't modify them in your server code. All these "models" exist as long as your HTML is being rendered on the server.
Client by itself won't be able to modify your database, only to modify it's HTML or send requests to your server.. It's your server code that actually modifies things.
Looking at this, and not knowing the context it is in, I would suggest using the domain model itself in your view and not wrapping it in the TicketViewModel. The ViewModel doesn't seem to add anything.
For the read only comments: I don't think it matters whether the collection in the ViewModel is editable. What matters is that you don't render editable controls in your view. And most important that the code in your Save (or whatever it is called) action ignores whatever comments are posted.
Related
I have an API which sends error status flag, error message and object of user. Currently I am using the API response class to get these responses.
public class UsersResponse
{
public int Status { get; set; }
public string Message { get; set; }
public List<User> Users { get; set; }
}
I receive the response in the instance of the above mentioned class and later display the result on the view. I get the response in the view's code behind file.
I was wondering if this is the right way to do it? If view models are used, will it be tackled by view model? If yes, then how will it be done.
I am thinking of getting into the habit of using view models rather than fully relying on the views code behind file.
The best way to tackle such a situation will be of great help and highly appreciated.
Thanks :)
Expose a INPC property like IsBusy in the ViewModel, turn it on before accessing your long running process (better make it async), then turn it off.
You shouldn't be loading data in the code-behind, in MVVM the code-behind should be minimized and restricted to view-specific only code (e.g. if you have several platforms). Think of code behind like JS for HTML, even less than that.
It's the ViewModel that should take care of loading the data and manipulating it. ViewModel = The model of the view.
My Home Model/View/Controller (which configures the initial state of the page) is working fine.
I also, though, need to respond to changes the user makes on the page (selecting an option from a select, checking a checkbox, etc.), and have not got that to work yet.
Maybe the reason I'm having problems is that I'm trying to reuse my "Home" model, which contains not only what I need for page initialization, but some other things as well. For example, my model:
public class HomeModel
{
public DataTable Units { get; set; }
public DataTable Reports { get; set; }
public DataTable UnitReportPairEmailVals { get; set; }
public DataTable UnitReportPairGenerateVals { get; set; }
. . .
}
...contains things the page needs at first ("Units"and "Reports" and the things represented by the ellipsis dots), but also things only needed later (the other two shown).
I'm wondering if at least part of my problem with getting this data back (via an Ajax call to another method in HomeController) is because I should be using a separate Model and Controller for the Ajax call.
So I'm wondering: is Model/Controller proliferation a code smell/anti-pattern, or necessary? Should I create another Model like:
public class AJAXModel
{
public DataTable UnitReportPairEmailVals { get; set; }
}
...and a corresponding separate Controller for it?
If I have a complex Model, which is used in various scenarios, it seems that every time I pass a model back as the return value (result) of an Action, a lot of superfluous/unpopulated things will also be passed back (only the members that I'm interested in at the time being populated in the Controller, thus passing back a lot of empty/null members).
So my question is, should I create spearate Models/Controllers for each "use case", or is it okay - or even better - to combine a bunch of things into one Model/Controller pair?
There's no compelling reason to limit a Model to a single Controller or to expect that a Controller has only one Model. You could write your entire app in a single Controller (really bad idea, by the way).
Generally, the division is a logical one...a bunch of actions that talk to the same set of Models in one controller. It's more to keep your brain from melting when you open the source file as anything else.
You often have multiple Views and they tend to mach name-for-name with the Actions in your controller...but this isn't strictly enforced.
When you feel like you're getting more data in the View than necessary, this can be simplified by mapping the Model to a ViewModel to simplify the code in the View. Yes, this is MVVM...and again...the brain hurts less dealing with the simpler object in the View.
You can manually map the object in your Controller, or you can use an auto-mapper to do it. There are a number to choose from...and they make the MVVM a simpler thing to do. You don't necessarily need one. They're just helpful.
I've written a little MVC3 site that let's certain users review Active Directory Accounts.
For audits we are required to keep track off our 'user reviews'. So, once a month I put everything in an SQL database. With the state 'to be checked'.
This looks like this:
I'd like to have a way that people can quickly approve them by just checking a textbox and saving it.
How would I go about this?
The 'ReviewState' is a separate object (StateID, StateText, Description, Active).
Possibilities are: Unchecked, Approved, Denied, Silently Approved, ...
Create a ReviewState model and a strongly typed partial view for it containing StateId, StateText, Description etc).
Your parent model should contain a list of ReviewStateModel's. In the main view, loop through that and render a partial for each model in the list.
You may need to add an Id so that you can identify each review model on the server side.
Create a ViewModel to be used in your view:
public class AccountViewModel
{
public AccountInfo Account { get; set; }
public ReviewState Review { get; set; }
}
This way you can add a checkbox for Approve like this:
#Html.CheckboxFor(x => x.Active);
You will get this model back to your post action. The only thing left is extract data and update database.
I might not be accurate with property names here and code is written from my head but I think you get the point
I'm creating a system using ASP.NET MVC for filling out online job applications. It's really just an experiment to familiarize myself with the MVC framework. I'm definitely not a security expert so I just wanted to get some advice here since this web app will be dealing with sensitive information.
The system has a wizard-like set of views. You go from one view to the next filling out the relevant information until the end when you finally submit it.
Each job application is stored in the database with a GUID primary key. Right now I am simply storing that GUID in a hidden field in the view of each page. This makes it easy to update the model in the controller like so:
[HttpPost]
public ActionResult ExampleAction(FormCollection formValues)
{
Guid appId = new Guid(Request.Form["ModelId"]); // the GUID stored in the hidden field
ExampleModel example = db.Entities.Single(e => e.ModelId == appId);
UpdateModel(example, formValues);
db.SaveChanges();
return RedirectToAction("ExampleAction2", new { appId = appId.ToString() });
}
I know this is not secure because anyone with any kind of development experience knows you can edit the values of hidden fields in any browser's developer tools. So what's the recommended way to securely get the same results?
You should store it in the Session object. That way, you can call it at anytime from anywhere and it will never display on any of your views.
The doc: http://msdn.microsoft.com/en-us/library/ms178581.aspx
I know this has been answered, just for interest sake I want to leave another option. How you could go about it is parsing the information you get from the first view as a JSON string that you can store in a cookie and then later serialize it when you need it.
This is asuming that the information is safe to store client side. Otherwise it could be an encrypted cookie I suppose. This would address the concerns for cloud computing and load balancers etc.
Why not post to each step instead of using RedirectToAction? That way you can create a model that contains each step.. for example:
class JobApplicationViewModel
{
public Guid ApplicationGuid { get; set; }
public StepOne Step1 { get; set; }
public StepTwo Step2 { get; set; }
public int CurrentStep { get; set; }
}
The step 1 view can post to step 2.. for example:
[HttpPost]
public ViewResult StepTwo(JobApplicationViewModel viewModel)
{
ServiceLayer.Update(viewModel);
return View(viewModel);
}
Then, the StepTwo view posts to StepThree, StepThree posts to Step4, etc. This makes sense logically, as you're only allowing people to get to any step beyond step 1 by posting the form.
I'm building a driver's application for employment and I'd like the list of 'accidents' to be dynamic in the sense of only one field appears, but they can add however many they need and once added they appear in a table above the input..
I'm trying to find out what the best way to do this is in a MVC3 Form that is using Razor syntax?
Model has a declaration similar to...
public class FormModel {
...other properties
public IEnumerable<AccidentDetail> AccidentDetails { get; set; }
...other properties
}
This is very much shortened, but wanted to ensure that I was declaring it properly in the model and then I need to know how it's generally handled in the Form to do something like this. I can't make any assumptions to the existence of an accident or the limit of how many they may have.
I personally would approach this with some JavaScript. In particular, I'd use jQuery to add a new field to the table when a button is clicked to "Add another accident". You can use jQuery to grab the values of the fields into an array. The array of accidents would be serialized to json and stored in a hidden field on the form that would be submitted to the server. In your controller you could deserialize that string of json to your strong type. On the server side I've used Json.NET with great success. On the client side you can use Doug Crockford's json2.js. Feel free to email me if you need a little bigger push in the right direction.