hi i am having a issue with MVC to make a controller even after reading the tips.
adding a constructor on the DbContext, deleting the non worked, changing providerName="System.Data.SqlClient" and so on.
my model class look like this:
public class RecruiterModel
{
public string CompanyName { get; set; }
public string Website { get; set; }
public string CompanySize { get; set; }
public string LinkedInCompanyURL { get; set; }
public string LinkedInID { get; set; }
public string Specialities { get; set; }
public string Category { get; set; }
public string Location { get; set; }
public int ContactPhone { get; set; }
public string ContactEmail { get; set; }
}
public class RecruiterDBContext : DbContext
{
public DbSet<RecruiterModel> Recruiters { get; set; }
}
and my web.config connectionStrings looks like this:
<add name="ApplicationServices"
connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true"
providerName="System.Data.SqlClient" />
<add name="RecruiterDBContext"
connectionString="Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\Recruiters.mdf;Integrated Security=True"
providerName="System.Data.SqlClient"
/>
any tips?
Add the following property to you Recruiter class:
public string Id { get; set; }
Or apply the Key attribute to one of you existing properties. For example:
[Key]
public string CompanyName { get; set; }
on MSDN, you have the Code First Conventions topic:
Primary Key Convention
Code First infers that a property is a primary key if a property on a
class is named “ID” (not case sensitive), or the class name followed
by "ID". If the type of the primary key property is numeric or GUID it
will be configured as an identity column.
public class Department
{
// Primary key
public int DepartmentID { get; set; }
. . .
}
Another reference on the topic is made in this Code First DataAnnotations article:
Key
Entity Framework relies on every entity having a key value (aka
EntityKey) that it uses for tracking entities. One of the conventions
that code first depends on is how it implies which property is the key
in each of the code first classes. That convention is to look for a
property named “Id” or one that combines the class name and “Id”, such
as “BlogId”. In addition to EF’s use of the EntityKey, the property
will map to a primary key column in the database.
I have found the solution to create the controller class:
On the model class i added the
using System.ComponentModel.DataAnnotations;
public class RecruiterModel
{
[Key]
public string Id { get; set;
then on the web.config i commented out the whole
connectionStrings tag
then i created the controller but and it worked.
thanks gos out to Alex Filipovici and Young Yang - MSFT on:
http://forums.asp.net/t/1888573.aspx/1?Unable+to+retrieve+metadata+for+when+trying+to+create+a+controller
though it works but on the Solution Explorer tab under App_Data i do not see the db file... hmm another issue.
Related
I'm attempting to setup a Web API endpoint that has a specific requirement that the XML format be similar to this:
<broadcast>
<name></name>
<description></description>
<episode>
<title></title>
</episode>
<episode>
<title></title>
</episode>
...
</broadcast>
My models look like this:
[DataContract]
public class broadcast
{
[DataMember]
public string name { get; set; }
[DataMember]
public string description { get; set; }
[DataMember]
public List<episode> episodes { get; set; }
}
[DataContract]
public class episode
{
[DataMember]
public string title { get; set; }
}
The problem I'm running into is that the episode items get put into a container tag <episodes>. Is there any way to serialize the episodes list so that the container tag doesn't appear?
As it turns out there is a way to do this, but you must use the XmlSerializer. To do this add the following line to to your WebApiConfig.cs
config.Formatters.XmlFormatter.UseXmlSerializer = true;
Then add the [XmlElement] attribute to any collections you don't have to have a root tag. If you want to have a root tag use [XmlArray]. So in my example above:
[XmlType]
public class broadcast
{
[XmlElement]
public string name { get; set; }
[XmlElement]
public string description { get; set; }
[XmlElement] // could use [XmlArray] if I want a root tag
public List episodes { get; set; }
}
[XmlType]
public class episode
{
[XmlElement]
public string title { get; set; }
}
Kyle's answer is almost correct. You need [XmlElement("episode")] for this to work.
As far as I know removing the root element in a collection type is not possible. This is subject of Collection Type Serialization and even though there are multiple options to alter how collections are serialized using attributes like CollectionDataContractAttribute there isn't an option to remove the root for the Serialized collection element.
You can use MessageContract instead DataContract. Message contracts describe the structure of SOAP messages sent to and from a service and enable you to inspect and control most of the details in the SOAP header and body:
[MessageContract]
public class broadcast
{
[MessageBodyMember]
public string name { get; set; }
[MessageBodyMember]
public string description { get; set; }
[MessageBodyMember]
public List<episode> episodes { get; set; }
}
Here you can find more information and details --> https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/using-message-contracts
I use MS Studio 2010 Express for Windows Phone to build the app. In my app, I got the http respond and read it in string then I deserializer into the class object. It works fine in the class without List collection as a property. When it deserializer the class with List property, it got the error like this
Error in line 12 position 5. Expecting state 'Element'.. Encountered 'EndElement' with name 'ContactList', namespace 'http://schemas.datacontract.org/2004/07/DataObjects’.
I think I can read the xml and assign the value into the class. I searched to read xml file and a lot of website mentions to use XDocument .Prase method or xlmDocument.Load. However event adding the System.Xml.Ling as reference , I still cannot see XDocument .Parse method or xlmDocument . Would someone tell me what I should do in order to assign the following value into the class?
There is my class object:
public class CallDetails
{
public int id { get; set; }
public string summary { get; set; }
public string errorMsg { get; set; }
public int parentCallid { get; set; }
public string parentCallURL { get; set; }
public string assignedTo { get; set; }
public string OrgName { get; set; }
public DateTime onHoldSince { get; set; }
public DateTime onHoldUntil { get; set; }
public string requester { get; set; }
public bool isOnHold { get; set; }
private List<Contact> m_ContactList = new List<Contact>();
public List<Contact> ContactList
{
get { return m_ContactList; }
}
}
There is the respond:
<?xml version="1.0" encoding="utf-8"?><CallDetails xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/DataObjects">
<ContactList>
<Contact>
<Method>PriPhone</Method>
<Number>(604) 555-1234</Number>
</Contact>
<Contact>
<Method>Fax</Method>
<Number>(604)555-1234</Number>
</Contact>
</ContactList>
<errorMsg
i:nil="true" />
<id>0</id>
<isOnHold>false</isOnHold>
<onHoldSince>0001-01-01T00:00:00</onHoldSince>
<onHoldUntil>0001-01-01T00:00:00</onHoldUntil>
<parentCallURL>/Call/349551</parentCallURL>
<parentCallid>0</parentCallid>
<requester>Peter </requester>
<summary>Mobile Application Research</summary>
</CallDetails>
Just adding the reference to System.Xml.Linq won't do it, you also need to reference the namespace in the class header:
using System.Xml.Linq;
Then you can call something like XDocument doc = XDocument.Parse(content);. However, from what I can tell, you are trying to deserialize data, so you might want to use the XmlSerializer class instead for all the core work. You can find some code 'ispiration' here.
I found it that the CallDetail Class cause error. It should be like that
public List<Contact> ContactList { get; set; }
Sorry about the title; couldn't think of a better one.
Any way, I'm accessing an associated property in my view like so:
#Model.Company.CompanyName // No problems here...
The model is a viewmodel mapped to an EF POCO. The Model has several properties associated to the Company table. Only one of the properties in the model share the same name as the PK in the Company table. All the other properties reference the same table:
public class MyModelClass
{
public int Id { get; set; }
public int CompanyId { get; set; }
public int AnotherCompanyId { get; set; } // References CompanyId
public int AndAnotherCompanyId { get; set; } // References CompanyId
public Company Company { get; set; }
}
public class Company
{
public int CompanyId { get; set; }
public string CompanyName { get; set; }
public string Address { get; set; }
}
I'm obviously missing something here.
How can I get the names of the other companies in my Model?
Any help is greatly appreciated.
The model is a viewmodel mapped to an EF POCO
I think you are confusing the notion of a view model. A view model is a class that is specifically designed to meet the requirements of your view. So if in your view you need to display the company name and not the company id then your view model should directly contain a CompanyName property. Or a reference to another view model (CompanyViewModel) which contains the name directly. It is then the responsibility of your controller action to query your domain models (EF entities) and aggregate them into a single view model tat will contain all the necessary information that the view requires.
Here's how a typical view model might look like:
public class MyViewModel
{
public CompanyViewModel Company { get; set; }
public CompanyViewModel AnotherCompany { get; set; }
public CompanyViewModel AndAnotherCompany { get; set; }
}
public class CompanyViewModel
{
public string Name { get; set; }
}
Where the data comes from in this view model is not important. You could have the Company property populated from your EF stuff, the AnotherCompany property populated from a XML file and AndAnotherCompany from WCF.
So I decided to go with the code first/DbContext approach, but already have an existing database file. Nothing complex, so I am thinking I can just create the DbContext derived container class with DbSets for the respective POCO's, create the connection string to my database and I should be set. However I believe I am having difficulties properly declaring the properties in my entity classes since I am getting errors when trying access an object through the navigational properties. Usually telling me Object reference not set to an instance of an object when I try context.Products.Find(1).Category.CATNAME; etc. Also tried declaring the collection properties with virtual keyword to no avail.
Some specifics of the database schema are:
In Categories table the PCATID is a foreign key to the CategoryID in
the same Categories table and can be null.
Both CategoryID and RootCategoryID in Products table can be null and
are both foreign keys to CategoryID in the Categories table.
I am testing things at the moment but will be setting a lot of the fields to non null types eventually.
Here are my entity POCO's and the entity Dbset container class:
public class Category
{
[Key]
public int CategoryID { get; set; }
public string CATNAME { get; set; }
public int PCATID { get; set; }
public ICollection<Category> Categories { get; set; }
public ICollection<Product> Products { get; set; }
}
public class Product
{
[Key]
public int ProductID { get; set; }
public int CategoryID { get; set; }
public int RootCategoryID { get; set; }
public string Name { get; set; }
public string ShortDescription { get; set; }
public string LongDescription { get; set; }
public string Keywords { get; set; }
public decimal ListPrice { get; set; }
public Category Category { get; set; }
}
public class EFDbContext: DbContext
{
public DbSet<Product> Products { get; set; }
public DbSet<Category> Categories { get; set; }
}
You need to make PCATID a nullable property as you have said it can be null. Make all those navigation properties and collection properties virtual. EF will not be able to detect the category hierarchy so you have use either attributes or fluent API to configure that.
public class Category
{
[Key]
public int CategoryID { get; set; }
public string CATNAME { get; set; }
[ForeignKey("ParentCategory")]
public int? PCATID { get; set; }
[InverseProperty("Categories")]
public virtual Category ParentCategory { get; set; }
[InverseProperty("ParentCategory")]
public virtual ICollection<Category> Categories { get; set; }
public virtual ICollection<Product> Products { get; set; }
}
Requirements for Creating POCO Proxies
Everything looks ready for POCO but Lazy Loading isn't sorted out at this point. By default LL is on, but in order to enable lazy loading, the Category property must be Virtual (a proxy is created that catches the reference and loads the data). If you don't want lazy loading then disable it in your EFDbContext constructor.
So your options are:
public virtual Category Category { get; set; }
or
public class EFDbContext: DbContext
{
public static EFDbContext()
{
LazyLoadingEnabled = false
}
...
}
You'd probably want to do the first one...
Are you certain you really want to use Code First? Or do you just want to use DbContext and DbSet? You can get the same benefits with Database First, using DbContext and DbSet. Since you already have a database, it's generally a lot simpler.
See: http://blogs.msdn.com/b/adonet/archive/2011/03/15/ef-4-1-model-amp-database-first-walkthrough.aspx
The only difference between Code First and Database First with DbContext is that Code first uses the fluent mapping model, while Database First uses an .edmx file. Maintaining the .edmx is much easier with an existing database.
If you're bound and determined to use Code First, then I suggest getting the Entity Framework Power Tools CTP1 and reverse engineering your database to Code First.
I agree with #Eranga about class Category (+1 to #Eranga).
public class Category {
[Key]
public int CategoryID { get; set; }
public string CATNAME { get; set; }
[ForeignKey("ParentCategory")]
public int? PCATID { get; set; }
[InverseProperty("Categories")]
public virtual Category ParentCategory { get; set; }
[InverseProperty("ParentCategory")]
public virtual ICollection<Category> Categories { get; set; }
public virtual ICollection<Product> Products { get; set; }
}
And you also have problem with your Linq query:
context.Products.Find(1).Category.CATNAME;
EF return data only from tables that you request with Include or you use this tables in functions.
With this code all work:
db.Products
.Include(p => p.Category) // here I demand to load data from Category table
.First(p => p.ProductID == 3)
.Category
.CATNAME;
I’m using ASP.NET MVC3. I have a model that has one property that I don’t want to store in the database. Is there an attribute that I can put on the property to achieve this? Thanks.
public class Person
{
[Key]
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
[NotMapped]
public string FullName { get; set; }
}
The attribute are in the namespace System.ComponentModel.DataAnnotations
Just to add more options... this is why I prefer to keep my domain model separate from my view model. My view model often has additional fields necessary for rendering the view which does not belong in the domain model. The design I typically use is described pretty well here.