In an asp.net MVC 1.0 application I have the following action
public ActionResult Submit(ContactModel model)
{
ContentResult ret = new ContentResult();
//do something
return ret;
}
Where ContactModel is defined as:
public class ContactModel
{
public string Name { get; set; }
public string Email { get; set; }
public string Subject { get; set; }
public string Message { get; set; }
public bool Authorization { get; set; }
}
Given that, in the Html Form that posts to this action, the names of the input tags are different from the names of the properties in the class ContactModel. Is there a way to map the html names to the class name so that the model binder can do its job?
The Bind Prefix (see How to use Bind Prefix?),
can partially solve this problem although doesn't allow the definition of full aliases for each property.
The Bind prefix has a strange behaviour though, because it assumes that between the prefix and the name there is a '.' (dot).
I don't think so.
You could create your own modelbinder though. See here for an example
Related
In my MVC web application I have the bellow class:
public class LoginVM
{
[Required]
public string Username { get; set; }
[Required]
public string password { get; set; }
public bool RememberMe { get; set; }
}
And in cshtml file I use EditorForModel to generate the form:
.cshtml
#Html.EditorForModel()
Now I want to know that is there any way to add some arbitrary attributes(for example css class attribute) to the html tag that is generating automatically?
Something like this:
...
[Required]
// Some code like this: [addAttribute("class", "myCssClass")]
public string Username { get; set; }
...
Agree with Comments by CodeCaster and Thorarins. It's not a good idea to mix up your Model with View related Attributes. In addition to using EditorTemplates/DisplayTemplates, you could also use the UIHintAttribute. It can help you to switch between different formats or also stylings within the View.
Some example:
http://www.shawnrenner.com/asp-net-mvc-custom-property-display-using-uihint/
I have a DbDataController which delivers a List of Equipment.
public IQueryable<BettrFit.Models.Equipment> GetEquipment() {
var q= DbContext.EquipmentSet.OrderBy(e => e.Name);
return q;
}
In my scaffolded view everything looks ok.
But the Equipment contains a HashSet member of EquipmentType. I want to show this type in my view and also be able to add data to the EquipmentType collection of Equipment (via a multiselect list).
But if I try to include the "EquipmentType" in my linq query it fails during serialisation.
public IQueryable<BettrFit.Models.Equipment> GetEquipment() {
var q= DbContext.EquipmentSet.Include("EquipmentType").OrderBy(e => e.Name);
return q;
}
"Object Graph for Type EquipmentType Contains Cycles and Cannot be Serialized if Reference Tracking is Disabled"
How can I switch on the "backtracking of references"?
Maybe the problem is that the EquipmentType is back-linking through a HashSet? But I do not .include("EquipmentType.Equipment") in my query. So that should be ok.
How is Upshot generating the model? I only find the EquipmentViewModel.js file but this does not contain any model members.
Here are my model classes:
public class Equipment
{
public Equipment()
{
this.Exercise = new HashSet<Exercise>();
this.EquipmentType = new HashSet<EquipmentType>();
this.UserDetails = new HashSet<UserDetails>();
}
public int ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Picture { get; set; }
public string Link { get; set; }
public string Producer { get; set; }
public string Video { get; set; }
public virtual ICollection<EquipmentType> EquipmentType { get; set; }
public virtual ICollection<UserDetails> UserDetails { get; set; }
}
public class EquipmentType
{
public EquipmentType()
{
this.Equipment = new HashSet<Equipment>();
this.UserDetails = new HashSet<UserDetails>();
}
public int ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<Equipment> Equipment { get; set; }
public virtual ICollection<UserDetails> UserDetails { get; set; }
}
try decorating one of the navigation properties with [IgnoreDataMember]
[IgnoreDataMember]
public virtual ICollection<Equipment> Equipment { get; set; }
The model generated by upshot can be found on the page itself. In your Index view you will see the UpshotContext HTML helper being used (given that you are using the latest SPA version), in which the dataSource and model type are specified.
When the page is then rendered in the browser, this helper code is replaced with the actual model definition. To see that, view the source code of your page in the browser and search for a <script> tag that starts with upshot.dataSources = upshot.dataSources || {};
Check here for more info about how upshot generates the client side model.
As for the "backtracking of references", I don't know :)
I figured out - partially how to solve the circular reference problem.
I just iterated over my queried collection (with Include() ) and set the backreferences to the parent to NULL. That worked for the serialisation issue which otherwise already breaks on the server.
The only problem now is the update of a data entity - its failing because the arrays of the referenced entitycollection are static...
To solve the cyclic backreference, you can use the IgnoreDataMember attribute. Or you can set the back reference to NULL before returning the data from the DbDataController
I posted a working solution to your problem in a different question, but using Entity Framework Code First.
https://stackoverflow.com/a/10010695/1226140
Here I show how to generate your client-side model manually, allowing to you to map the data however you please
I have a model like the followings:
public class MyModel {
[Required]
public string Name { get; set; }
public string Family { get; set; }
[Required]
public int Number { get; set; }
}
So for example in Edit View I have 3 Editorfor() objects and I am interesting to filter the post data of this page, actually I want to ignore Number field and just want to post Name and Family Also I need the validations of Number be active, One way is I remove Number property from MyModel and define in view by hand and write all validation script by own, but I am interesting to know is there any simpler way in MVC. Does anyone have any idea?
Controlling all that validation and model binding manually is way too complicated and error-prone. You should be using ViewModels
public class SomeSpecificViewModel
{
[Required]
public string Name { get; set; }
public string Family { get; set; }
}
public ActionResult SomeSpecificAction(SomeSpecificViewModel model)
{
//...
}
Now MVC wil validate only Name and Family
Any value not filled in the view will not be posted to the controller. However, if a field which is [Required] is not filled, then ViewModel.isValid will be false.
I have an object like this
public class ParentEntityInfo
{
public long? ParentId { get; set; }
public string EntityName { get; set; }
public string ParentProperty { get; set; }
}
and view for this object is:
<%=Html.Hidden("parentInfo.ParentId", parentInfo.ParentId)%>
<%=Html.Hidden("parentInfo.ParentProperty", parentInfo.ParentProperty)%>
<%=Html.Hidden("parentInfo.EntityName", parentInfo.EntityName)%>
I have the case where parentInfo is null and I post this form to controller. On the controller action
public ActionResult SomeAction(..., ParentEntityInfo parentInfo)
I receive constructed object parentInfo but all properties are null. In this case I would rather prefer to have whole parentInfo to be null. I there any possibility to tell default model binder do not pass such object? Or probably I can modify something in this code to make it work this way. I think in mvc 2.0 it worked this way.
Use the HiddenFor(...) helper instead.
I think the default model binder will always use Activator.CreateInstance to bind complex action parameters. What you can do is use ModelState.IsValid to assess whether the parameter was bound successfully. I think in your case this will be false by default, but if not you could add the necessary attribute to ensure this behaviour e.g.
public class ParentEntityInfo
{
[Required(ErrorMessage = "Parent required")]
public long? ParentId { get; set; }
public string EntityName { get; set; }
public string ParentProperty { get; set; }
}
i'd like to know, I have a application in asp.net mvc and nhibernate. I've read about that in the Views on asp.net mvc, shouldn't know about the Domain, and it need use a DTO object. So, I'm trying to do this, I found the AutoMapper component and I don't know the correct way to do my DTOS, for some domain objects. I have a domain class like this:
public class Entity
{
public virtual int Id { get; set; }
public virtual bool Active { get; set; }
}
public class Category : Entity
{
public virtual string Name { get; set; }
public virtual IList<Product> Products { get; set; }
public Category() { }
}
public class Product : Entity
{
public virtual string Name { get; set; }
public virtual string Details { get; set; }
public virtual decimal Prince { get; set; }
public virtual int Stock { get; set; }
public virtual Category Category { get; set; }
public virtual Supplier Supplier { get; set; }
public Product() { }
}
public class Supplier : Entity
{
public virtual string Name { get; set; }
public virtual IList<Product> Products { get; set; }
public Supplier() { }
}
I'd like to get some example of how can I do my DTOs to View ? Need I use only strings in DTO ? And my controllers, it should get a domain object or a DTO and transform it on a domain to save in repository ?
Thanks a lot!
Cheers
There is no guidelines on this matter and it depends on your personal chice. I have few advices that have proven useful in practice:
1. Use flat DTOs - this means that the properties of the DTO must be as primitive as possible. This saves you the need for null reference checking.
For example if you have a domain object like this:
public class Employee
{
prop string FirstName{get; set;}
prop string LastName{get; set;}
prop Employee Boss{get; set;}
...
}
And you need to output in a grid a list of employees and display information for their 1st level boss I prefer to create a DTO
public class EmployeeDTO
{
prop string FirstName{get; set;}
prop string LastName{get; set;}
prop bool HaveABoss{get;set}
prop string BossFirstName{get; set;}
prop string BossLastName{get; set;}
...
}
or something like this (-:
2. Do not convert everything to sting - this will bind the DTO to a concrete view because you'll apply special formatting. It's not a problem to apply simple formatting directly in the view.
3. Use DTOs in your post actions and than convert them to domain objects. Usually controller's actions are the first line of deffence against incorrect data and you cannot expect to be able to allways construct a valid domain object out of the user's input. In most cases you have to do some post-processing like validation, setting default values and so on. After that you can create your DTOs.