MVC - Multiple Model One Data - model-view-controller

For example, in an IDE application, say for C#, there are 2 views ClassView and TextView.
In ClassView we need to display the Class information in a hierarchical manner, where as in TextView the code for that Class is shown.
The ClassView needs to query for classes, methods, properties, fields, etc. whereas the Text View queries lines in the code.
Both the views are editable. Change in one view should be reflected in the other view too.
So Class View requires one model and Text View requires another but the underlying data is the same.
Is there a design pattern to solve such a problem?
Thanks in advance.

Certainly an MVC model can be hierarchical. If your data is all contained in a single file, maybe you don't really need multiple models for your application? How about:
namespace MyNamespace
{
public class CodeFile
{
/// <summary>
/// A list of contained classes for the Class view
/// </summary>
public List<CodeClass> Classes { get; set; }
public CodeFile()
{
Classes = new List<CodeClass>();
}
public string ToString()
{
// send output to Text view
}
}
public class CodeClass
{
public string ClassName {get; set;}
public List<CodeProperty> Properties {get; set;}
public List<CodeMethod> Methods {get;set;}
public CodeClass(string className)
{
ClassName = className;
Properties = new List<CodeProperty>();
Methods = new List<CodeMethod>();
}
}
public class CodeMethod
{
public string MethodName { get; set; }
}
public class CodeProperty
{
public string PropertyName
}
}

Model View Controller :)
The mistake in your question is that your data is actually mapped on your model.
You can have 2 views (classview and textview) and they both works with one single common model. Controller can update one view when another one changes the model.

You tagged it yourself with MVC... The underlying data is the model, the Class View and Text View act as views/controllers. The model sends out events to its views, to make sure that changes in one view are reflected in the other.

There's nothing in MVC architecture to prevent writing multiple model hierarchies which interact with the same underlying data store.
You would just have Controllers/Views which interact with Model A, and different Controllers/Views which interact with Model B.

Related

How to make single controller for two database classes - MVC3

I have two database classes as defined below:
public class TopDate
{
[Key]
public int DateId { get; set; }
public DateTime Date { get; set; }
}
public class TopSong
{
[Key]
public int SongId { get; set; }
public string Title { get; set; }
public int DateId { get; set; }
}
where DateId is foreign key to TopSong
I am creating a controller through which i can create, delete or edit these database values.
When i right click on controller class and add controller i can only select one of the two classes defined above. Is there a way to make 1 controller to handle database updates to both these tables on one page?
Error Image:
Your controller should not be dealing directly with domain objects (meaning those things that are directly associated with your database). Create a ViewModel that contains the properties that you need, use your service layer to populate the ViewModel and your controller will use that as the Model for its base. An example of your ViewModel could be something like the following given your description above:
public class MusicViewModel
{
public int SongId {get;set;}
public string Title {get;set;}
public IEnumerable<DateTime> TopDates {get;set;}
}
This view model would contain a list of all dates that a specific song was a Top Song.
The objects you showing (code) are database classes (so called domain objects).
What you need to do is to define a view model, a standard ASP MVC practice:
you define a class, that is tailored for specific view and only containing data relevant to that particular view. So you will have a view model for a view that will create a song, another that will update it etc.
Actually situation you describing is classical situation to use view models. Using domain objects in the views, however, is really really bad practice and prone to more problems than you want to deal with.
Hope this helps.

Giving error while creating partial class

I am developing MVC application in which , I am trying to create the partial class of class generated by MVC application lets say Location class.
Now I want to create the partial class of Location class in new class file.
The below class code is auto genrated by MVC of Location code.
namespace CRM
{
public partial class Location
{
public int Id { get; set; }
public string Name { get; set; }
public string Remark { get; set; }
}
}
I have added new class file which contain the partial class of above file
namespace CRMEntities.Partial_Class
{
public interface ILocation
{
[StringLength(50, ErrorMessage = "Region can accept maximum 50 characters.")]
string Region { get; set; }
[Key]
int Id { get; set; }
[Required]
string Name { get; set; }
string Remark { get; set; }
}
public partial class Location : ILocation
{
}
}
Its giving the below error...
CRMEntities.Partial_Class.Location' does not implement interface member 'CRMEntities.Partial_Class.ILocation.Name
First, you don't need to do this, what I understand is you are trying to do validation right? Think about, the object generated by EF is not ViewModel, they are domain model. Data annotation should be in View Model, not domain model.
Most of cases, often mis-use is to use domain model as view model, but it is not correct much. Because sometime, view models need more than one domain model to provide data for your UI.
So for separation of concerns, you need to define your View Model different with domain model.
Example: you have Location class, you need to add LocationViewModel class and put data annotation in here.
You can map manually or use AutoMapper for mapping bettween View Model and Domain Model.
Another solution is you can use Fluent Validation, with this way, needless to have more partial class just for validation.
You don't show the definition of ILocation in your question, but the error says that the Location.Name property is declared differently than the ILocation.Name member.
Edit: Your two partial classes appear to be in two different namespaces, hence they are actually two entirely different classes, not two parts of the same class. That would explain the compiler error.
Having said that, I do agree with the other answer (+1!) that you should do your UI validation on a view model instead.

MVC Code First C# Retrieve Data

Ok So I am just simply needing good instructional pages on how to design a Class for retrieving data from the database.
I can find information all over on how to take an existing database and create an Entity Framework from it but I am trying to do code first.
I am able to insert Data (although I am not 100% sure how that is working) I just cannot seem to figure out how to pull the data from the database using the class(Model) that is created and display that data on a Razor page.
I have no problem with doing the studying and learning this but I am having a terrible time at finding good information that will just do a true walk through of this process.
Once again I am not looking for the Entity Framework.
Thank you for all of the help you can provide.
There is a lot of tutorials out there in the internet. Here is a small example to pull your data from table and show in the view.
Assuming you have a model class called User like this
public class User
{
public int ID { set;get;}
public string FirstName { set;get;}
}
Add properties like this to your DataContext class for each of your model entities. The property is of type DbSet.
public class YourDataContext: DbContext
{
public DbSet<User> Users {set;get;}
}
Then in your controller action method, you can create an instance of your DBContext class and access its Users property. Pass that to our view.
public class UserController : Controller
{
public ActionResult Index()
{
YourDBContext db=new YourDBContext();
var users=db.Users.ToList();
return View(users)
}
}
Have an index.cshtml view like this under Views/User folder.
#model IEnumerable User
#foreach(var user in Model)
{
<p>#user.FirstName</p>
}

mvc3 validation when using buddy classes

I am working on an mvc3 application and having some problems with getting validation to work as I want.
The application is using buddy classes for the models. (This is something I haven't used in the past and I am a little confused why they are used...anyway)
I want to add required fields to ensure data been submitted is correct. I have tried adding the required field to the buddy class.
When I submit the form no client-side validation takes place and the debugger steps into the entity frameworks generated code. Here is complains that the fields that contain null values are causing are invalid. If I step through all of those it finally gets to the controller where my if (ModelState.IsValid) is showing false.
I have client-side validation switched on.
Am I meant to be applying the data validation at the buddy class level or at the view model?
One other question is why use buddy classes? to me they seem to over complicate things.
Updated added an example of the buddy class
[MetadataType(typeof (CustomerMetaData))]
public partial class Customer
{
public string Priorty
{
get
{
var desc = (Priority) Priority;
return desc.ToString().Replace('_', ' ');
}
}
internal class CustomerMetaData
{
[Required]
[DisplayName("Priorty")]
public string Priorty { get; set; }
Buddy classes are metadata classes to put data annotation attributes when you are not in control of the original class i.e. can't edit it. Typical situation is when the class is generated by an ORM like Entity Framework.
//Can't edit this class
public partial class YourClass{
public string SomeField {get; set;}
}
//Add a partial class
[MetadataType(typeof(YourClassMetadata))]
public partial class YourClass{
}
//And a metadata class
public class YourClassMetadata
{
[Required(ErrorMessage = "Some Field is required")]
public string SomeField {get; set;}
}
are you sure that you have [MetadataType(typeof(YourClassMetadata))]?
More about buddy classes here and here
You would typically use a buddy class when it isn't possible to add meta data to an entity class such as when a model is automatically generated by an ORM tool. In this case any meta data you had applied would be lost.
Therefore, your original (automatically generated) class would be defined as a partial class:
public partial class Customer
{
public string Priority { get; set; }
}
And then you would generate your buddy classes to add the meta data.
[MetadataType(typeof(CustomerMetaData))]
public partial class Customer
{
}
internal class CustomerMetaData
{
[Required]
public string Priority { get; set; }
}
You would then pass the Customer class to the view where the Priority would be set.
In your case i'm not sure if you only have one partial class or two (as the other is not shown but please provide if there is). I'm interested to know how you obtain the priority information from the customer as i'm wondering if this is an issue with how you use ModelState.IsValid? The reason I ask is that no set accessor is declared on the Priority property so i'm wondering how this is set from the view in order to report that it is not valid?
You would also use a buddy class when it isn't possible to add meta data to an entity class such as when a model is automatically generated by an WCF Data Contract.

How to work with navigation properties (/foreign keys) in ASP.NET MVC 3 and EF 4.1 code first

I started testing a "workflow" with EF code first.
First, I created class diagram. Designed few classes - you can see class diagram here
Then I used EF Code First, created EntsContext..
public class EntsContext : DbContext
{
public DbSet<Project> Projects { get; set; }
public DbSet<Phase> Phases { get; set; }
public DbSet<Iteration> Iterations { get; set; }
public DbSet<Task> Tasks { get; set; }
public DbSet<Member> Members { get; set; }
}
Next step was creating a ProjectController (ASP.NET MVC3) with simple action:
public ActionResult Index()
{
using (var db = new EntsContext())
{
return View(db.Projects.ToList());
}
}
The problem is: I am not getting a ProjectManager in view (List/Create scaffolding used). I would like to know if I am doing this wrong or scaffolding generation just ignores my properties, that aren't basic types.
Hmm... It is probably quite obvious.. because generator doesn't know what property of that Type should be used, right?
Well then I could modify my question a bit: What's a solid way to create a Project entity in this scenario (I want to choose a project manager during project creation)? Should I make a ViewModel for this?
ProjectManager will not be loaded by default. You must either use lazy loading or eager loading. Eager loading will load ProjectManager when you query Projects:
public ActionResult Index()
{
using (var db = new EntsContext())
{
return View(db.Projects.Include(p => p.ProjectManager).ToList());
}
}
Lazy loading will load ProjectManager once the property is accessed in the view. To allow lazy loading you must create all your navigation properties as virtual but in your current scenario it isn't good appraoch because:
Lazy loading requires opened context. You close context before view is rendered so you will get exception of disposed context.
Lazy loading in your case results in N+1 queries to DB where N is number of projects because each project's manager will be queried separately.
I believe you'll need a ProjectManager class, and your Project entity will need to have a property that points to the ProjectManager class.
Something like:
public class Project
{
public string Description {get; set;}
public Member ProjectManager {get; set;}
}

Resources