Model - Partial class and Datacontext class are not communicating - asp.net-mvc

I've created a one table contact DB, which has only 3 columns (Id, Name, and Phone). I've then created the ContactsDataContext using my table Contacts in the model folder. Finally, I create a partial class still in the model folder (public partial class Contact).
now when I write this
public partial class Contact
{
public string MyContact
{
get
{
string name = this.Name ?? String.Empty;
}
// ... Other lines omitted
}
}
I get the following error :"'ContactsManager.Models.Contact' does not contain a definition for 'Name' and no extension method 'Name' accepting a first argument of type 'ContactsManager.Models.Contact' could be found (are you missing a using directive or an assembly reference?)"
Is something wrong??? Even the Intellisense in not showing the properties from my DataContext class. Yet, I've written some partial classes in the past with no problem.
Thank you.

Are namespaces the same on the two partials?

Chris Roden,
Yes, I've resolve it. In fact, I've asked the above question many months ago when I started learning ASP.NET MVC. I bought a book called "ASP.NET MVC - The Beer House/Nick Berardi/Wrox." Is a god book, but it's not recommendable for beginners. Generaly, things are thrown like that without telling where they come from.
The response came from applying the definition of a partial class. Among others, partial classes must:
have the same name
be preceded by 'partial' keyword,
be defined in the same namespace,
etc.
If you miss any of the above criteria, then you'll be in trouble because those criteria, ll be used to merge all the partial classes into a unique one.
In my case, I created a table called ContactDB. After I've created the datacontext class, I've dropped the ContactDB table on the Linq2Sql editor. As you must know, that creates the following class:
public partial class ContactDB
{
//All the columns in the table become properties in this class
}
The partial keyword allow me to write this:
public partial class ContactDB
{
//I can reference members of the above partial class... using this keyword
//After all, the 2 constitute one class.
}
After reading the definition of partial classes, I found out that I failed one of the criteria. I called my other partial class "Contact" which's different from ContactDB. That was enough to make me go crazy for 3 days until I read the definition. Moreover, if you defines the partial class with the right name but you put it in a different namespace, you'll get in trouble as well.
So, if the above answer doesn't work for you (I don't know exactly your problem), check the definition of the partial class.Don't forget to read the ScottGu's series on Linq2Sql.
Hope it helps.

Related

How do I validate a Modelbound item without violating DRY in ASP.NET MVC?

I'm using the ASP.NET MVC DefaultModelBinder to bind a request to a model class, but only using two of its properties:
namespace MVCApp.Models
{
public class Ticker
{
public string Symbol {get; set;
public string Exchange {get; set;}
}
}
namespace Domain //in another assembly
{
public class Quote
{
public string Symbol {get; set; }
public string Exchange {get; set; }
//lots of other properties we need for output
}
}
public ActionResult ShowQuote(Ticker ticker)
{
var quote = quoteRespository.GetQuoteBy(ticker);
return View(quote);
}
In the view, they can specify the Ticker and Exchange; and that's ModelBound using the DefaultModelBinder. However, each time we need to actually use this Ticker object for something, we need to go to the QuoteRespository and get all of the properties populated for that Ticker.
Question
Should I get rid of the Ticker Object and just create a custom modelbinder to Model-bind to the Quote object; and in the Modelbinder make the respository calls to actually fill out the Quote object? Or should I violate DRY and make the call to that respository in every place we need a quote? Is there a built-in framework way of doing this that I'm missing?
It appears there is a school of thought that says not to make service-layer calls in the Modelbinder.
Update
I created the Ticker class just because we had these two properties in (almost) every single action:
public ActionResult ShowQuote(string symbol, string exchange)
Since they always belong together, I created a small Model class in the UI layer to push them around together (the aforementioned Ticker class). Ticker is not a view model class, and it isn't meant to be.
"Or should I violate DRY and make the call to that respository in every place we need a quote? Is there a built-in framework way of doing this that I'm missing?"
You could always retrieve the quote as part of a Quote controllers OnActionExecuting function.
I wouldn't consider this a DRY violation. Just the cost of doing business. Chances are the way you retrieve quotes won't change and you'll probably have < 10 places were you need this functionality. Depends on how many times you'll need to include that line.
Better to have short and concise action methods than getting all mangled up in base controller and onactionexecuting stuff.
Don't get into model binding against your repository. Did it in a previous project and its the worst and most brittle piece of the application.
I would use AutoMapper to map between view models and domain models.
For me it would be important to see what does Quote contains ? You mention it has other properties for output but does it have other properties and methods which are only relevant to the Domain namespace? If yes then I would like to keep an abstraction between the types used for views and the types in your domain namespace.
So you could end up having a TicketViewModel which contains everything required by your views and as Darin mentioned, use AutoMapper to map TicketViewModel to Quote.
EDIT:
If you really want to ensure DRY, then you can create your own ModelBinder (it's easy, tons of tutorials on Google) and bind your viewmodel from repository in it.

What is meant by "convention" in this context?

I recently read this blog entry by Hadi Hariri: That dreaded M in ASP.NET MVC. Hadi surveyed fellow ASP.NET MVC developers about the types of models they use in the applications. One of his survey questions read:
If you bind to Domain Model, how do you deal with extra data such as country list?
And one person wrote select Other and wrote in: "conventions." Following that, Hadi wrote:
I've actually found another way to solve this problem, partially based on conventions.
And then later says:
Maybe we should take the concept of conventions more seriously than just what folders our Views, Controllers and Models reside in. Maybe we should push conventions to the limit and see if we actually reduce this friction.
What does he mean by using "conventions" to solve this problem? I'm not familiar with the term in this context.
Thanks
Convention in this context could mean many things. Loosely it is just a solution to the problem that is not built in but looked up using names.
An example of this already in MVC is that a route to a controller named "Home" is mapped to a class named "HomeController". Extending this idea to the selected country and country list problem you can think of many solutions.
One example would be given a model:
public class UploadModel
{
public string Country {get; set;}
}
We may define options for this model via a convention on the naming where it looks for a model with the word "Options" after its name and then matches the property on the model with a like named property on the options model.
public class UploadModelOptions
{
public IList<string> Country {get;set;}
}
This may not be a great convention but is an acceptable example of what the author may be talking about.

Should I use entity-framework classes or model classes in the Controllers?

I am new to entity framework and mvc.
I am trying to understand what a Controller should pass to the view.
Should it be the class from Models (MySolution.Models.Story) or the class from the entity framework (MySolution.Story).
The problem is that if I pick the one from entity framework, then the DataTypes and html-helpers are not working correctly. If I pick the class from models, then I can't convert from the entity class to the model class, for example:
TrendEntities TrendDB = new TrendEntities();
public ActionResult Details(int id) {
var Country = TrendDB.Countries.FirstOrDefault(c => c.CountryId ==id);
return View(Country);
}
Just use the adp.net entity framework POCO templates to generate. download the template. right click in the entity designer and select "add code generation item" and choose the poco template. Now your objects dont have all of the 'entity framework baggage' with them. Proxies are automatically created behind the scenes and you don't need to do any object mapping.
You can find this template by adding a new item to visual studio 2010, and searching the online templates from within the add dialog for POCO. The template name is:
ADO.NET C# POCO Entity Generator
You are looking for either AutoMapper or ValueInjecter. These two libraries are "Object to Object" mappers, which are designed for mapping values from one object to another object. I have only used AutoMapper before. It is great and pretty easy to pick up. I've heard good things about ValueInjecter as well.
After some investigation, I figured out that I had a design problem.
Long story short, REMEMBER that in MVC 3 we need a to define the following class in the model
public class StoryDBContext : DbContext
{
public DbSet<Story> Stories {get; set;}
}
And then in the controller THAT's the one to use when accessing the Entity Framework.
In the previous version we were not defining the above class and were using the TrendEntities class (that was created by the framework) to access the DB.
That's a bit confusing...
So, in my example, TrendDB should be of type StoryDBContext instead of TrendEntities and things are working as expected.
Use a ViewModel. This is a class that you declare having the properties you want to display on your View.
For example:
var country = TrendDB.Countries.FirstOrDefault(c => c.CountryId == id);
CountryDetails details = new CountryDetails();
details.FirstValueToShow = country.Name;
return View(details);
Remember to strongly type your Details view to the ViewModel.

MVC 3 Custom Templates and EditorForModel confusion

So as I understand it
Given a view model
public class MyViewModel{
public DateTime Date {get; set;}
public MyClass Class {get; set;}
}
.. a View Views\MyController\MyAction.cshtml
#model MyViewModel
#Html.DisplayForModel()
.. a partial View Views\Shared\DisplayTemplates\DateTime.chstml
#model DateTime
Some Date
.. another partial View Views\Shared\DisplayTemplates\MyClass.cshtml
#model MyClass
My Class
.. I should get
Date
Some Date
Class
My Class
.. But I just get
Date
Some Date
So it seems DisplayForModel finds DateTime template but not my custom template, even though I am following the conventions of naming it by the type of the property.
Am I missing something. I am using MVC 3 and believe this feature was already available in MVC 2
Having perused the MVC source code, it turns out that this is, in fact, not possible.
The reason is that #Html.DisplayForModel() attempts to find a template to use for rendering, by:
first looking for the name of the model's type, i.e. MyViewModel.cshtml or MyViewModel.vbhtml or MyViewModel.ascx etc, in location ~\Views, ~\Views[ControllerName], ~\Views\DisplayTemplates, ~\Views\Shared, ~\Views\Shared\DisplayTemplates
if it is not found it will walk down the model's base types, attempting each type's name in turn
if none are found, it will eventually end up at Object, for which there exists a built-in template
The object template is designed such that it retrieves all the model's properties, for rendering, from metadata based on the following condition:
metadata.ShowForDisplay
&& metadata.ModelType != typeof(EntityState)
&& !metadata.IsComplexType
&& !templateInfo.Visited(metadata)
Therefore any property that is a complex type will always be excluded. I think the confusion arises from Brad Wilson's post on custom object template, where he creates a custom object template and addresses the issue of Shallow Dive vs Deep Dive. By implementing a custom deep dive object template this will override the built-in object template and complex types can be rendered.

Does ASP.NET MVC Has Anything Equivalent To WPF's DataTemplate Feature?

In my ASP.NET MVC project, I have a polymorphic collection that I wish to render - say, an IEnumerable<ISomething> where the individual items may be a mix of different implementations of ISomething.
I'd like that list rendered, where each concrete type renders according to its own template (perhaps a strongly typed ViewUserControl).
In WPF, I'd be able to specify DataTemplates that would automatically bind concrete types to specific templates. Can I do something similar in ASP.NET MVC?
Obviously, I can iterate through the list and attempt a cast using the is keyword and then use a lot of if statements to render the desired control, but I was hoping for something more elegant (like WPF).
I ended up with developing a solution myself - I have described it in DataTemplating In ASP.NET MVC.
I'm not sure if I get you fully, but, why don't you implement a method to your ISomething interface like render for example, which by contract will be implemented to all of your other concrete entities, and then iterate through each item in the polymorphic collection and call it.
I had a similar issue and never found a "simple" answer. I had the benefit of knowing that all items in the list would render the same way so I created a decorator for ISomething, converted the list to IEnumerable using some code from the Umbrella project (http://umbrella.codeplex.com), and then extracted out the relevant pieces. Kinda like the following:
public interface ISomethingDecorator
{
string Description { get; }
string[] Actions { get; }
}
public class BigSomethingDecorator : ISomethingDecorator { /* ... */ }
public class SmallSomethingDecorator : ISomethingDecorator { /* ... */ }
Then, as I said, I use the Umbrella project to convert from ISomething to ISomethingDecorator and returned IEnumerable to the View.
Don't know if it'll help you with what you're trying to do -- especially being a month late -- but I thought I'd let you know how I handled it. If you're displaying completely different formats, it probably won't do the trick but maybe it can get you a starting point.

Resources