Controller/View don't recognize a new model - asp.net-mvc

I have my asp.net MVC project with some models generated from the DB.
Now I want to add some new models "manually" (without being generated from the DB) called "TrainingViewModels" to be used on the views.
The problem is that the models inside TrainingViewModels file are not recognized in any controller/view. Below the content of TrainingViewModels.cs:
namespace FMS.Models
{
public class TrainingAdminViewModel
{
public Training Training { get; set; }
public List<UserTrainings> UserTrainingsList { get; set; }
}
}
If I paste the code above on AccountViewModels.cs file everything work as expected. I don't understand why I can't have it declared on a diferent file.
P.S. - It is not a missing import problem I think

Related

Entity Framework creates an empty migration file

I created my initial project in Visual Studio and discovered I had used SQL Server after I created my initial migration. I then changed all the connection information to use MYSQL and connected successfully. I created the initial migration again and it created all the ASP security tables. I added a new model and updated the database, but it created an empty migration (just UP/DOWN methods)
I've tried multiple fixes I found here and other sites. I backed out the second migration and retried. I tried forcing the migration again (-f). I dropped the new MYSQL db and deleted the migrations then started over, all with the same result.
Here is my model code:
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace congresssucks_conversion.Models
{
public class BlogPost : DBContext
{
public int Id { get; set; }
public string Title { get; set; }
public string ShortPost { get; set; }
public string Post { get; set; }
public string Tags { get; set; }
public DateTime Updated { get; set; }
}
}
And here is the migration file:
namespace congresssucks_conversion.Migrations
{
using System;
using System.Data.Entity.Migrations;
public partial class blogpost : DbMigration
{
public override void Up()
{
}
public override void Down()
{
}
}
}
It completes successfully and no errors in the Terminal Window.
You're combining two separate things, your model class and your database context.
Your BlogPostm class shouldn't inherit DbContext, it should be just a plain C# class.
Then you make a new class that looks something like this:
public class BlogDbContext : DbContext
{
public DbSet<BlogPostm> Posts { get; set; }
}
Now you have a class that can represent a single post, and another class that can represent a database with a table of multiple blog posts. The migration generator is looking for those DbSet<whatever> properties, so you should see real migrations after this change.
There are a lot more ways you can describe what you want Entity Framework to do with your database, so it would be worth reviewing an Entity Framework tutorial.
Try to delete a record of last migration from _MigrationHistory table. Maybe This record had been incorrectly created before added DbSet for the new model object to DbContext class. After this delete, new migration was created with correct Up() and Down() methods.

Nested view model - modifying generated name of input fields with EditorFor HTML-helper

Recently by stumbling across some CQRS I like to seperate the concept of a view model from the concept of a request (command), where the command is what is posted to the server. For example there's no reason for me to include select lists in what's posted to the server. Trying this out I've had some design issues, especially when playing with MVC-views.
In my system there's a complex role based authorization and for that I need 6 different views for editing a member. All of those views edit personal info exactly the same, so I created an editor template for it. The editor template has a view model as model and not a command. This is because I need the select list in the editor template. This works well until it comes to the model binding - because of wrong input names. I know I can put write input names manually with #Html.Editor but I rather not.
My classes below are heavily slimmed down for readability, there are tons more of properties.
I have a view for editing a member. Here's its view model:
namespace Features.Members.Edit.AsAdmin
{
public class ViewModel
{
public Command Command { get; set; }
public PersonalInfoViewModel PersonalInfo
=> new PersonalInfoViewModel {Command = Command.PersonalInfo };
}
public class Command
{
public PersonalInfoCommand PersonalInfo { get; set; }
}
}
I have an editor template for the PersonalInfoViewModel.cs which I use in the main view with:
#Html.EditorFor(x => x.PersonalInfo)
The other classes:
namespace Features.Members.Shared.Form.ViewModels
{
public class PersonalInfoViewModel
{
public PersonalInfoCommand Command { get; set; }
public SelectList BusinessAreas { get; set; }
}
}
namespace Features.Members.Shared.Form.Commands
{
public class PersonalInfoCommand
{
public int? BusinessAreaId { get; }
}
}
Now what I need is the editor templates inputs to model bind to the main Command. That means the name of the input should be:
PersonalInfo.BusinessAreaId
However the generated input field names are like this:
<select class="form-control" id="PersonalInfo_Command_BusinessAreaId" name="PersonalInfo.Command.BusinessAreaId"></select>
Is it possible to modify the generated input names? Is this MVC design not good? Are there any alternatives?

MVC Scaffolding with Repository Pattern - Saving children objects as a transaction

I have been scouring forums and repository pattern blogs for some clear direction on how I should be coding my project and I'm stuck. Any help or guidance from you guys would be much approciated :)
I started my project as EF5 MVC4 Razor Code First and decided to use MVCScaffolding to generate all my controllers, views and repositories. This was my first project with these technologies, I was just told that this was how the team was doing it now (but the previous developers did model first and hand coded their contexts).
SO, all is great, we're coding a bunch of screens, but one of our screens is a complex one that involves many models/sub modlels (ie/ Object model has FKs to Responses, Attachments, Reviewers, etc...). The user adds a bunch of data, selects one or more reviewers, adds 0 or more attachments. Then they hit Save!
Now my big problem is that I want to save all this data as one transaction, and if something fails on one of the children models (ie/ attachments) the transaction will roll back. However, the way the MVCScaffolding repositories are created, each model has it's own instance of DB Context and it's own Save. And the controllers accept each unique repository as parameters for loading the screen data. Another thing to note is for this screen we are using a ViewModel to load the data, and then wrote custom mappers to map back to the different models for saving. We can save each piece separately, and possibly the solution is just to wrap TransactionScope around my save, but I also want to reduce the number of calls to the db, as each repository save does a call.
I thought I could add code to the parent repository for a UnitsOfWork type save that would add/edit all the child obejcts in one context object, but that seems like a hack more than anything, and I want to code this properly.
One of the other projects here just made a custom DB context and all Save methods were in that class, is that the best way to do it? Another dev did code first but hand coded all his Save methods. None of them are in a standard place and he is using TransactionScope with a DBContext inside (is that overkill or does DBContext not handle transactions)?
Since I'm so new to this, I need help and no one I work with seems to agree on a proper method. I'm not sure if my model is wrong for an "MVC App" since I'm such a database heavy thinker.
Below is a sample of my models, any guidance is appreciated. Thanks :)
public class Anomaly
{
[Key]
public int AnomalyId { get; set; }
public string Subject { get; set; }
public int PlantId { get; set; }
[ForeignKey("PlantId")]
public virtual Plant Plant { get; set; }
public DateTime? ReviewByDate { get; set; }
public virtual ICollection<AnomalyReviewer> AnomolyReviewers { get; set; }
public virtual ICollection<AnomalyAttachment> AnomalyAttachments { get; set; }
}
public class AnomalyAttachment
{
[Key]
public int AnomalyAttachmentId { get; set; }
public int AnomalyId { get; set; }
[ForeignKey("AnomalyId")]
public virtual Anomaly Anomaly { get; set; }
public string FilePath { get; set; }
public string FileName { get; set; }
public string FileExtension { get; set; }
public string Notes { get; set; }
}
ps. that is just a sample... thanks!
Just create a class 'Master' that inherits from Controller.
Then write all your queries there as in public User GetUserById(Int32 id)
Finally create a function that does a call to the private!! implementation of DbContext.
I would usually give that function a enum of SystemEvents so i've got a reference of whats happening if something would fail... of course you would need to write your own notificator or model to record your own errors into the database for personal testing...
ive done all this because I can write all my code and found out that Repository Pattern is overkill most of the time if you actually think about it.

T4 Self Tracking Entities And Model Validation

I'm using EF4.x Self Tracking Entities in my project and am trying to achieve Model Validation in my MVC4 web application, however, my Model State always seems to be Valid. I'm using T4 templates to generate my "buddy" classes. Below is an example of one of the STE's and its buddy:
STE - generated using T4:
[DataContract(IsReference = true)]
[KnownType(typeof(Filing))]
public partial class FilingHistory: IObjectWithChangeTracker, INotifyPropertyChanged
{
public int FilingHistoryId
{
//Snipped for Brevity
}
// Navigation, ChangeTracking, Association Fix up snipped
}
Here is the Buddy Class generated also via a T4 template I wrote:
[MetadataType(typeof(FilingHistoryMetaData))]
public partial class FilingHistory
{
// Partial Class
}
public class FilingHistoryMetaData
{
[Display(Name = "Filing History Id")]
[Required(ErrorMessage = "Filing History Id is Required.")]
int FilingHistoryId { get; set; }
// Other properties snipped for Brevity
}
I'm going to exclude the key's from each MetaData class because those will be created automatically (just as an fyi). Also, the namespaces for the STE, the empty partial and the buddy class are identical
When I create a simple controller in MVC4 just to test it out, with a Create Template, on the HttpPost Action of Create I have some code as shown below:
[HttpPost]
public ActionResult Create(FilingHistory filingHistoryToCreate)
{
if (ModelState.IsValid) // THIS IS ALWAYS TRUE! even if i pass nothing<----
{
return Redirect("/");
}
return View(filingHistoryToCreate);
}
I read through a bunch of SO links and even went through MSDN, and I think I have everything setup correctly, i.e. namespaces are fine so there is no naked partial class stuff going on.
When my view renders I leave all the textboxes empty, I set a breakpoint to inspect by entity and nothing has been set, yet the model is valid. I also tested by entering some garbage into the textboxes to ensure the model binding was working fine, and it was...
I tried also testing using a console application, and I found out that you have to take an additional step of registering the MetaData type, but I beleive in MVC this isnt required. In case it helps anyone - the console app and registering meta data type didn't work for me either, so I'm thinking my buddy class may be the culprit?
It seems the DataAnnotationsModelMetadataProvider is looking for the public properties when checks for the attributes.
Change your FilingHistoryId to public and it should work:
public class FilingHistoryMetaData
{
[Display(Name = "Filing History Id")]
[Required(ErrorMessage = "Filing History Id is Required.")]
public int FilingHistoryId { get; set; }
// Other properties snipped for Brevity
}

How do I use my own Model classes in conjunction with EF entity classes in MVC?

So I am new to MVC and am working now with MVC3 and the Entity Framework. I am currently using a Model/Schema 1st approach as the database already exists. Therefore I create my ADO.NET Entity Data Model (.edmx) and I have all the needed entities in my MVC app. So far so good on all this.
However let's say one of my Entities is a 'Customer' entity. I can see the auto-generated partial class inheriting from EntityObject in MyEntites.Designer.cs. At this point I want to add some custom business logic to my MVC Model. Natuarally I believe the answer is to use my own partial class created in the Model named 'Customer' as well.
I did a lot of searching on this before asking the question and see all kinds of information on POCO, T4 templates, modifying auto-generated code, etc and am lost. Is it a royal pain to add my own business logic and custom code to the auto-generated entities from EF? I certainly don't want to modify the auto generated code over and over.
I need a straight forward explanation to make the proverbial 'light bulb' go on, and then I can take-off from there. Can someone help me answer how to do this please?
Thanks!
Keep your own class code in a different file, but use the same class and namespace. This will help avoid your code being overwritten by the T4 code generator.
Extending Entity Framework Generated Types
You can also add attributes to generated classes by using a meta class:
Adding Attributes to Generated Classes
Those codes are auto-generated and will be over written on each model update or change.
You can achieve what you need through extending models. Suppose that EF generated the following entity class for you:
namespace YourSolution
{
using System;
using System.Collections.Generic;
public partial class News
{
public int ID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public int UserID { get; set; }
public virtual UserProfile User{ get; set; }
}
}
and you want do some work arounds to preserve your you data annotations and attributes. So, follow these steps:
First, add two classes some where (wherever you want, but it's better to be in Models) like the following:
namespace YourSolution
{
[MetadataType(typeof(NewsAttribs))]
public partial class News
{
// leave it empty.
}
public class NewsAttribs
{
// Your attribs will come here.
}
}
then add what properties and attributes you want to the second class - NewsAttribs here. :
public class NewsAttrib
{
[Display(Name = "News title")]
[Required(ErrorMessage = "Please enter the news title.")]
public string Title { get; set; }
// and other properties you want...
}
Notes:
1) The namespace of the generated entity class and your classes must be the same - here YourSolution.
2) your first class must be partial and its name must be the same as EF generated class.
Go through this and your attribs never been lost again ...

Resources