My problem is that I want to partially edit my model - to display 2 fields and to edit another 2 fields for example. When POST happens, returned model contains only the fields that are editable, other fields that I use only to display are NULL. How to fix this, on POST to be returned model with all fields, because on ERROR when I return this model and fields are NULL is not so good?
The model binder binds the form values only to model properties that have a setter.
Depending on what you need to achieve:
You can use hidden inputs to store the values in the view, these will be bound back (given that the properties have a setter)
<%= Html.Hidden(Model.SomeField) %>
class YourViewModel
{
public SomeField {get; set;}
Or you should ensure in your controller action that you are only updating the fields that you displayed in the view, not the null ones.
Ideally, your viewmodel should contain only the properties that are relevant for the view (and for the logic handled by the controller).
Related
tl;dr
I need an edit form for a uni-directional many-to-many relationship (doctrine), where the resulting join table has extra inherited properties. Is there a way to achieve this through the FormBuilder?
Entities
I have a uni-directional many-to-many relationship (doctrine), where the resulting join table has a relation to a third entity.
Form
The User edit-form should allow (un)crossing Deals easily through a checkbox, while also showing the relations' inherited fields from Discount. The discount's properties should be inherited from Deal by default and overridden on the UserDeal object if modified.
My approach
The way I have approached this, is by creating an auxiliary object UserDealState with two properties: a boolean active and a reference to the UserDeal. UserDealState has its own Type (checkbox and Discount fields).
I also added a transformer that converts the array of UserDeals to an array of UserDealStates, adding all the non-joined Deals (and setting active to false).
When I check the form inspector in the Symfony Profiler, I can see the transformation has taken place (the view data holds a collection of UserDealStates and is a much longer collection than the model data that holds a collection of UserDeals, which makes sense), but the form object only holds the amount of UserDealStates formViews that the original collection had of UserDeals had, not the much larger number it should.
Just to give a concrete example: say we have 10 Deals, and only one crossed UserDeals. On my form {{ form.userDeals.vars.value|length }} returns 10, {{ form.userDeals.children|length }} returns 1. Only one subform is rendered instead of 10.
Hera are my form-types: UserType, UserDealStateType, UserDealType, DiscountType.
Transformer: UserDealStateToUserDealTransformer
The question
How do you render a form with FormBuilder to edit the mapping between two entities in a many-to-many relationship and the relations' extra fields (as shown on the form mock-up above)?
I have two entities: product and category (Symfony 2.3).
I want to create a form in which an user can choose a product by first selecting the category. A user selects the category by clicking on image, then I want to set the image's value into a hidden input, but I don't see how can I change a foreign entity choice list to a hidden input (http://symfony.com/doc/current/reference/forms/types/entity.html).
How can I accomplish this? (how to change form input to hidden)
If I set cascade validation to true, will it for example check if a category really exist. (To prevent putting products with non-existing category from malicious users) ?
Part 1
To do this you need to use a data transformer to do two things:
transform an entity into an identifier that is either a string or integer so a form can render it as a hidden field.
transform the string or integer identifier into the entity when the form is submitted so that the parent entity can be saved with the correct relationship
The symfony docs I linked to above (here too) actually walk though an entire example of using a data transformer with a form.
As a shameless plug (because I believe it is helpful) I have written a little tutorial on using a data transformer for a hidden field with an entity id: http://lrotherfield.com/blog/symfony2-forms-entity-as-hidden-field/
Part 2
If you are using the data transformer then you don't need to worry about malicious users. The data transformer will fail because it will not be able to reverse transform the category from the fake id. In my tutorial the transformer will throw a Symfony\Component\Form\Exception\TransformationFailedException exception.
You can also write a validator (potentially using a call back) if you wanted that checks that the submitted category is real if you want an error to show in the form. Doctrine wont allow you to persist a fake category relationship as the foreign key constraint will fail.
I'm using Entity Framework 4.1 with a code-first model. A common pattern is that many objects reference the user who owns them, eg.
public class Item
{
public User Owner { get; set; }
}
This creates a nullable column in the DB, but since every Item must have an owner I want the column marked NOT NULL. If I use the [Required] attribute then submitting the form to create an Item results in an error. That field is never set through a form, only manually in code.
It is generally recommended to create separate view models for such situations. Using database models as view models for input forms is seen as an anti-pattern.
Make a ItemViewModel that has the same properties as Item and relevant data validation attributes. You may want to use a library called Automapper to automate the boring property-copy-code needed in those cases.
I have a form in my MVC 2 application that allows a user to update a set of fields from a model object, this is purely an update as the model object is already existing with its required fields entered. However when I try to update a small set of fields and call TryUpdateModel on my model object it fails and my modelstate has errors based on required fields that have already been filled out.
Here is my controller code:
[HttpPost]
public ActionResult Work(int id, FormCollection forms)
{
var lead = claimRepo.GetLeadByID(id);
if (lead == null)
return View("NotFound");
if (TryUpdateModel(lead, "Lead")) {...}
}
I've even tried explicitly stating which fields to update like so
TryUpdateModel(lead, "Lead", new string[] { "Date", "UserID", ...}) {...}
And it still fails, is there some reason this doesn't ignore validation on fields not included or am I doing something wrong?
Thanks!
EDIT
I found the issue, I had a property on my class that wasn't database backed and was marked as required in metadata, so adding a getter and setter to return what the property represented caused the TryUpdateModel to pass, but I am still curious as to why the explicit include of properties didn't ignore the field I hadn't included.
Another Edit
I have a user model as well with all database backed required fields and trying to explicitly state which fields are being updated still results in modelstate errors on the fields missing in the form, but are filled in on the model object from the db that is being updated.
I am not sure when the default behaviour was changed for validating only incoming data, from what I know I think only asp.net mvc1 supported it, then it changed in asp.net mvc2 anyway you could say [Validate(false)] and allow the partial data to go through and manually do some validation. You could use a ViewModel and validate all fields on the view model if needed as a second option. A helpful link: partial validation
I'm looking for advice on a decent pattern for dropdown list selection and persistence of the selection with POCO EF please.
I have a list of IEnumerable<Country> in my view model where Country is a POCO loaded via EF. There is an Address property on the view model that takes the current or user selected value on it's Country property. Within the view I display these via a Html.DropdownListFor() thus:
Html.DropDownListFor(model => model.Address.Country.Id, new SelectList(Model.Countries,"Id","Name",model.Address.Country.Id)
So far so good and it all works on postback with the default ModelBinder providing me with a view model with the Address.Country populated. However Address.Country is of course only populated with the Id field with default model binding.
Trying to send the Address update back to the DB through EF blows up as this is seen as a new object which doesn't have it's full object graph loaded, only the Id set.
Now I can fix this by loading the full Country object from the db into the Address.Country property on postback before saving based on the selected Id. But this seems like a lot of hard work for anything beyond a simple object graph.
The most "elegant" solution I could think of would be a custom model binder for Country but then that would require the Model Binder to know about the repository for retrieving the full EF object which doesn't seem right to me. I'd also have to repeat this for all other Entities used in Dropdown lists.
Hope this makes sense and any feedback on how others are doing this would be appreciated.
If you set Address.Country to an object, EF expects it to be a full object that's part of the current context, but EF does recognize foreign keys: If your Address object has both a CountryID property and a Country property, it should accept Address.CountryID being set as long as Address.Country itself is null.
In your Address class declare country as virtual
public class Address
{
public virtual Country Country;
}
try this and let me know if it works, Virtual supports lazyloading and you don't have to query explicitly