It seems that to skip a member to come on a View you can set ScaffoldColumn attribute to false in your model
[ScaffoldColumn(false)]
public object Id { get; set; }
but here i see that Id is of object type. Is this the only way? I tried with
[ScaffoldColumn(false)]
public int Id { get; set; }
but it didn't work. How can i prevent scaffolding on a primitive type e.g. int,long etc.
Edit
I have define my model as
public class Department
{
[ScaffoldColumn(false)]
public int Id { get; set; }
[Required(ErrorMessage="Name is required")]
[StringLength(25)]
[DisplayName("Name")]
public string Name { get; set; }
public bool Active { get; set; }
}
I have a controller having action Create. When i right click on create action and select add view and create a strongly type view with this model it creates a view but also adds a textbox for Id
<%: Html.TextBoxFor(model => model.Id)%>
which i suppose it shouldn't have
ScaffoldColumn only changes the behavior of methods like Html.DisplayForModel() which actually use the default templated views system introduced in MVC 2. It does not affect the Visual Studio wizards that ship with MVC.
To change that, you need to edit the T4 templates, somewhat like this.
I wouldn't bother, though. If you want scaffolding in MVC 2, I think it's better to use default templated views than the "Add View" scaffolding, which is code generation.
Related
I'm defining two entities like the following, but a strange behavior is occurring:
[Table("ClientTypes", Schema="dbo")]
public ClientType {
[Key]
public int Id { get; set; }
public string Name { get; set; }
}
[Table("Clients", Schema="dbo")]
public Client {
[Key]
public long Id { get; set; }
[ForeignKey("ClientTypeId")]
public int ClientTypeId { get; set; }
public virtual ClientType ClientType { get; set; }
}
I'm getting the ClientTypeId property filled with some value, but the ClientType object is filled with nothing. Can someone help me with this?
Thank you all!
The ForeignKey attribute as you have it is on the wrong property.
The annotation may be placed on the foreign key property and specify the associated navigation property name, or placed on a navigation property and specify the associated foreign key name.
- source
[ForeignKey("ClientTypeId")] should decorate public virtual ClientType ClientType instead,
or change it to [ForeignKey("ClientType")] and leave it where it is.
Are you eagerly loading the value?
var clients = context.Clients.Include("ClientType").ToList();
When selecting the Client you have to Include the client type
Client cli = (from c in db Clients.Include("ClientType")//or the name of the property
select c).First();
This translates to a left join and selects the data for Client and ClientType.
If you skip the Include the EF will select the data only for the client when execute the statement.
As Mike said if the context is still available the property will be lazy loaded when you access it.
I generated Entity Model from my database in my MVC5 App.
When I try to add [DispalyName] to some properties it works fine, but after some time app refreshes this class by itself and removes all my custom code
public partial class Patient
{
public Patient()
{
this.PatientDetails = new HashSet<PatientDetail>();
}
public int PatientID { get; set; }
[DisplayName("Last Name")]
public string LastName { get; set; }
public string FirstName { get; set; }
public virtual ICollection<PatientDetail> PatientDetails { get; set; }
}
Why MVC does it and how to disable that?
I believe since you're using Database first, the entities will get completely re-created every time you refresh, thus you lose your custom attributes.
Also, to go off of Joe's comment, you should make a view model and put your [Display] attributes there and not directly on the entity.
In an MVC4 web application using the Razor engine and entity framework, is it possible to create a template for use with the html helper #Html.EditorForModel , so that entities with links to other tables are better displayed.
The example I am working with is a DbContext containing two DBSets, Regions and Schools. There are many regions, and a school may belong to one region. Ideally I would like the editor for schools to show a dropdown of regions to select from. I would like to make a template that is generic enough so that I can just call the #Html.EditorForModel helper and the form is generated in one go, and that I could make changes to the region or schools tables later on and for the changes to be reflected in the edit form without me needing to make alterations.
Some code:
public class MyContext : DbContext
{
public MyContext ()
: base("DefaultConnection")
{
}
public DbSet<Region> Regions { get; set; }
public DbSet<School> Schools { get; set; }
[Table("Regions")]
public class Region
{
public Region()
{
Schools = new List<School>();
}
[Key]
public int RegionId { get; set; }
[StringLength(256)]
public string RegionName { get; set; }
public ICollection<School> Schools { get; set; }
}
[Table("Schools")]
public class School
{
public School() { }
[Key]
public int SchoolId { get; set; }
[StringLength(256)]
public string SchoolName { get; set; }
[ForeignKey("Region")]
public int RegionId { get; set; }
public virtual Region Region { get; set; }
}
}
I have created a partial view to create display the editor form, with the idea that I can pass in either a Region or a School as the view model.
#model object
#using (Html.BeginForm())
{
#Html.ValidationSummary("Broken stuff:")
#Html.EditorForModel()
}
I don't know if this is possible, but I would really like the new template to loop over the properties of the entity and detect if there is a linked table (e.g. School contains a Region) and display the list of regions in a dropdown.
Well, in general, it's a bad idea to pass your data models directly to your views for rendering. There are security issues there, among other things. But, even if you are going to do this you would not want to pass your entire data context like that because it's not structured in a way that is suitable for rendering in a web page.
Off corse you can. Look at here to see how.
An alternation is that you use scaffolding and let it to create your views. Most of times(!) it creates correct DropDowns for you and you just customize your view if you want.
And in those few situations that yo see strange DDLs, you just need to correct ValueName and DataName parameters in the related action methods whic return list items to the view...
please have a look at the following POCOs:
public class Country
{
[Key]
public Guid ID { get; set; }
[Required]
public virtual Currency Currency { get; set; }
}
public class Currency1
{
[Key]
public Guid ID { get; set; }
public virtual ICollection<Country> Countries { get; set; }
}
public class Currency2
{
[Key]
public Guid ID { get; set; }
}
I am not exactly sure what I need navigation properties like the ICollection in Currency1 for. If it comes to EF CodeFirst I see no difference in the database structure created. The tables of Currency1 and Currency2 look pretty much the same to me. So why or when does it make sense to add this extra property?
Of course, just thinking of the POCOs I understand that I can't access any countries from a Currency2 object. For example:
var a = currency1.Countries; // works fine
var b = currency2.Countries; // does not even compile
But is this the only difference? In other words: If I do not need to access countries from a Currency2 object, there is no need to add a corresponding navigation property in the Currency2 class for the purposes of EF? Kind of confused here...
Navigation properties are used either for direct access (as you described) or in linq-to-entities queries. If you don't plan to use it you can remove it from your model. Just be aware that you need a navigation property on at least one side to be able to model database realation using the code first approach.
I have two view models:
public class MasterPageViewModel
{
public string Meta { get; set; }
}
public class Entry : MasterPageViewModel
{
public int EntryID { get; set; }
public string Title { get; set; }
public DateTime PubDate { get; set; }
}
Index page returns a list of entries, so in the view contains:
...Inherits="System.Web.Mvc.ViewPage<IEnumerable<bl.Models.Entry>>"
Then the master page contains
...Inherits="System.Web.Mvc.ViewMasterPage<bl.Models.MasterPageViewModel>"
And here is the error that I am getting:
The model item passed into the dictionary is of type 'System.Linq.EnumerableQuery`1[bl.Models.Entry]', but this dictionary requires a model item of type 'bl.Models.MasterPageViewModel'.
I can easily bypass that error by using ViewData dictionary on the master page, but in my case I would prefer strongly typed approach. In future I want to be able to add lists of categories and tags that would appear on the master page.
I have something like the structure you describe in an MVC site I'm working on now. I haven't found a really satisfying answer -- in many cases it feels like you want two distinct models, one for the master page and one for content pages. Unfortunately, that's not how MVC works.
I've only come across one solution, other than the ViewData option you mentioned.
Base Class
Build a base class that all your models inherit off.
The base class contains all the properties you need in your master page.
Good: it's simple inheritance
Bad: you end up with wrapper methods / models for basic things like passing an enumberable collection.
So in your case you would end up with something like ...
public class MasterPageViewModel {
public string Meta { get; set; }
}
public class Entry : MasterPageViewModel {
public IEnumerable<bl.Models.EntryItem> Items {get; set }
}
public class EntryItem{
public int EntryID { get; set; }
public string Title { get; set; }
public DateTime PubDate { get; set; }
}
And your Index page would look like...
...Inherits="System.Web.Mvc.ViewPage<bl.Models.Entry>"
It's kind of a pain in the butt because you end up with lots of little models. Once I got used to it, however, i've stopped thinking about it.
HTH,
-eric