I have a situation in ASP.NET MVC 2 where I have a form whose fields are based on info supplied by a view model, but whose posted data is a subset of that data represented by a slimmer edit model. I'd like to add simple data annotation validation to the edit model, but since the view is based on the view model, I'm not sure how to proceed.
View model and controller action parameters don't have to be the same.
In your case this means that you may be using a richer model class to generate your view (and maybe even posting more information than needed) but your controller action would only use some information from that posted data to populate a simpler application model object instance. No problem. As long as field naming will suffice to populate properties correctly.
You may have these two classes:
public class User
{
[Required]
public string Username { get; set; }
[Required]
public string Password { get; set; }
}
public class Person: User
{
public string Name { get; set; }
public string Address { get; set; }
}
and then your view would be using Person and your controller action would have a parameter of type User. Fine. It will work.
There's no need for these classes to inherit each other either. I've just made it so in this simple example because this way they both share common property names. But otherwise they don't have to be related in any way shape or form as long as posted field names will be able to model bind to controller action parameter class properties.
Related
I have a non-content data in a record class as follows.
public class StudentRecord{
public virtual int Id { get; set; }
public virtual string Number { get; set; }
public virtual string Name{ get; set; }
public virtual string Description { get; set; }
}
I want to write its export and import. Any idea or just direction will be helpful.
Regards,
I have also reported this question in Orchard Pros: http://orchardpros.net/tickets/9329
You should not use Repositories to access your data as it is not very performant and breaks the 'Orchard way' of doing things.
you can treat your part as any other part. looking at your model, it does not even seem you might need the record.
A Part is nothing more than a Model with its Entity (DDD) or a wrapper to contain data and logic.
How about just inheriting from ContentPart not ContentPart and access your Object's data with the Infoset methods: Store, Retrieve. then you can use a Part Driver to just have the Import and Export behaviours in it.
If you need to query against your part then do inherit from ContentPart where T is your Part Record, still using the Store, Retrieve.
Are you attaching this part to any Content Type? If you give us more context on how this part will be used, you might have a more specific answer.
How is this part generated? how is it edited?
So if I have the following entity:
public class Guest
{
public int GuestId { get; set; }
public bool HasCheckedIn { get; set; }
// child/related entities
public Person Person { get; set; }
public Address Address { get; set; }
public Phone Phone { get; set; }
}
Please forgive/correct me if some of the terminology I use is not correct...
Assume we have turned off Navigation Properties which would automatically populate the child entities such as Person and Address.
If my website is calling the WebApi for specific data, sometimes it might need the 'full' Guest object with all of the child entities, in which case it might call the appropriate method in the Business Layer to backfill the object. In other cases, to keep the request light we might just want a 'shell' or 'brief' of the Guest with just the basic data that the underlying table would hold such as HasCheckedIn and all the child entities to just be null.
So what is the suggested approach here for the Api Controller? Should there just be one Persons Controller who's Get method is really a proxy to the GetFull method in the BLL Person class and then have a separate PersonsBrief Controller who's Get method is really a proxy to the GetBrief method in the BLL Person class? Or should this be one method in the Persons Controller which takes in a boolean for IsBrief or something?
Both approaches have merit but it may actually be clearer to separate the summary and details into separate resources. It seems like your use cases between the two variations are distinct, which to me suggests that you should separate your resources accordingly. In other words, implement two separate controller methods, one for "guest details" and another for "guest summary".
This is a design problem specific to a Web API project I'm working on, but it might be a question that's general to REST principles. It's also possible I'm completely overthinking this.
I have a class in Entity Framework that has a child collection of another class:
public abstract class Tracker
{
[Key]
public int ID { get; set; }
[MaxLength(50)]
public string Name { get; set; }
public virtual ICollection<Unit> Units { get; set; }
}
The Unit class looks like this:
public class Unit
{
[Key]
public int ID { get; set; }
[MaxLength(50)]
public string Name { get; set; }
}
I'm working on a Web API that will GET a list of trackers, and GET a list of available units, then add a particular unit to a tracker's list of units. Trackers and Units have their own API controllers and repositories and I'm trying to figure out how to modify them to support creating this association, and what the request would look like.
Is it appropriate to update the Tracker endpoint (/Trackers/1) via PUT to add a new Unit to the list, maybe along with the existing Units? How would I handle that on the back end? I think one of the mental hurdles I have with the PUT approach is - would I include the entire child object in the request body collection property? It wouldn't make sense to, but I'm not sure how it would work otherwise. The assumption (in my case) would be that the Unit being added to the Trackers list would be one that already exists and we're just creating the association. Should I maybe use DTOs for both of these to accomplish this more simply and map them accordingly?
Or would it make more sense to create some new joint DTO like "TrackerUnit" with a corresponding endpoint that I can add new associations to by POSTing to that endpoint (POST /TrackerUnits), then handle the processing in a new controller for it? I would think it would also need to support a DELETE to remove the items. I'm not crazy about this approach since this endpoint wouldn't correspond to any actual resources in my system, but just be used for mapping these associations.
How about creating an endpoint:
/Trackers/{id}/units
and then you can Post a Unit to this endpoint to associate with the Tracker identified by the {id}, or similarly:
DELETE /Trackers/{id}/Units/{unitid}
to remove a Unit.
I'm new to MVC and I'm trying to figure out how to implement business logic in the auto generated Entities in an MVC project.
I know that if I create my own Model class I can put [Required] and other attributes on the fields but there doesn't seem to be an option to do that in the .edmx file.
Is there something I'm missing here?
Should I be creating my own classes that use the entities and put the logic in there?
It seems like there should be a way for me to do less work.
Thanks!
This can be achieved by using the buddy-class functionality in .NET implemented specifically for this reason. Once you have created your entities in your .ebmx file you can create partial classes to accompany your entities which define your business rules in a 'buddy class'.
[MetadataType(typeof(ProductMetadata))]
public partial class Product {
internal sealed class ProductMetadata {
[DisplayName("Name")]
[Required]
public string Name { get; set; }
[DispayName("Price")]
[Required, Range(1,10000)]
public decimal Price { get; set; }
[DisplayName("Description")]
public string Description { get; set; }
}
}
In the example above, assume that you already have a "Product" type defined in your object context which has properties for "Name", "Price", and "Description". So long as the buddy class type referenced by the MetadataTypeAttribute has matching property names, the attributes applied to the properties in the buddy class will be applied to the implementation type.
Note: if there are any property names in the buddy class which do not match the implementation type, you will get a runtime error. You only need to create matching properties in the buddy class for the properties you are interested in applying business rules to; all properties are optional.
I want a list of different (derived) object types working with the Default Modelbinder in Asp.net MVC 2.
I have the following ViewModel:
public class ItemFormModel
{
[Required(ErrorMessage = "Required Field")]
public string Name { get; set; }
public string Description { get; set; }
[ScaffoldColumn(true)]
//public List<Core.Object> Objects { get; set; }
public ArrayList Objects { get; set; }
}
And the list contains objects of diffent derived types, e.g.
public class TextObject : Core.Object
{
public string Text { get; set; }
}
public class BoolObject : Core.Object
{
public bool Value { get; set; }
}
It doesn't matter if I use the List or the ArrayList implementation, everything get's nicely scaffolded in the form, but the modelbinder doesn't resolve the derived object type properties for me when posting back to the ActionResult.
What could be a good solution for the Viewmodel structure to get a list of different object types handled? Having an extra list for every object type (e.g. List, List etc.) seems to be not a good solution for me, since this is a lot of overhead both in building the viewmodel and mapping it back to the domain model.
Thinking about the other approach of binding all properties in a custom model binder, how can I make use the data annotations approach here (validating required attributes etc.) without a lot of overhead?
Check out the Derived Type ModelBinder in MvcContrib. This allows you to modelbind to derived types through the process of 'typestamping' - which is handled automatically for you when using the RenderTypedPartial(...) helper. MvcContrib partials maintain binding state across partials so the Name/Id prefixes are properly maintained on a deep object graph. If you use other mechanisms like templates, then you'll need to handle the typestamping yourself. This is explained in the documentation page.
Getting back to your questions and how the derived types are resolved with the ModelBinder, you can register the derived type variations with attributes in a mechanism similar to the WCF KnownTypeAttribute or you can do the registration on startup. Either way, these variations are registered once and held onto for performance considerations.
The model binder also solves this problem in a way that does not interfere with data annotation/validation attributes. They will work as you expect them in any other scenario.