I have entity class in created using entity framework which is in my Domain project
using System;
using System.Collections.Generic;
public partial class Test
{
public int Id { get; set; }
public int ExamID { get; set; }
public string TestName { get; set; }
public string StartDescription { get; set; }
public string EndDescription { get; set; }
}
And In my MVC application I am creating one viewmodel which I use in my view
public class TestViewModel
{
public Test Test { get; set; }
}
Now I want to make fields related to "StartDescription" and "EndDescription", for this is am trying to use TinyMCE.
Now the problem is "[AllowHtml]" attribute is in mvc but my real entity is in other project
I am following this tutorial.
http://www.codeproject.com/Articles/674754/TinyMCE-and-ASP-NET-MVC-advanced-features
Rather than your view model having an instance of Test it should contain the properties you wish to use in the view. You can then add the [AllowHtml] attribute to the properties in your view model without affecting your domain objects.
public class TestViewModel
{
public int Id { get; set; }
[AllowHtml]
public string StartDescription { get; set; }
[AllowHtml]
public string EndDescription { get; set; }
}
In your controller you would then need to map the view model to your domain class.
Old post but thought this might be relevant for someone else:
borrowing a sample code from petelids and modifying it.
public class TestViewModel
{
public int Id { get; set; }
[UIHint("tinymce_jquery_full"), AllowHtml]
public string StartDescription { get; set; }
[UIHint("tinymce_jquery_full"), AllowHtml]
public string EndDescription { get; set; }
}
Providing the UIHint on the model object you can place your tinyMCE script code in a file saved in the Folder
~/Views/Shared/TemplateEditor
I do this using the TinyMCE4.MVC libraries - however mine is modified a bit for my own special workings that I have added.
Related
I am developing an application in asp.net mvc. I use entity framework as ORM. I have a problem. To use javascript unobstrusive validation, I need to add annotation to model objects. For example; [Required], [EMailAddress]. But when we add something to the database and update it, all model classes are override, and all annotations disappear. Or, as soon as you open edmx, automatic model classes are automatically override. How can I solve this problem. There are dozens of screens and classes, the slightest change in edmx erases the annotation in all classes, causing huge waste of time.
// <auto-generated>
using System.ComponentModel.DataAnnotations;
namespace MerinosSurvey.Models
{
using System;
using System.Collections.Generic;
public partial class Surveys
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Surveys()
{
this.SurveyQuestions = new HashSet<SurveyQuestions>();
this.SurveyCustomers = new HashSet<SurveyCustomers>();
}
public int SurveyId { get; set; }
[Required(ErrorMessage = "Plase enter survey name.")]
public string SurveyName { get; set; }
[Required(ErrorMessage = "Please enter survey description.")]
public string SurveyDescription { get; set; }
// [DataType(DataType.Date)]
public System.DateTime? CreatedDate { get; set; }
//[DataType(DataType.Date)]
public System.DateTime? UpdatedDate { get; set; }
public int CreatedUserId { get; set; }
public bool IsActive { get; set; }
public bool Status { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<SurveyQuestions> SurveyQuestions { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<SurveyCustomers> SurveyCustomers { get; set; }
public string Token { get; set; }
}
}
Editted for
Metadata
Surveys Partial & Metadata
//PartialClass
[MetadataType(typeof(SurveyMetadata))]
public partial class Surveys
{
}
//Metadata
public partial class SurveyMetadata
{
public int SurveyId { get; set; }
[Required(ErrorMessage = "Lütfen anket adını giriniz.")]
public string SurveyName { get; set; }
[Required(ErrorMessage = "Lütfen anket açıklamasını giriniz.")]
public string SurveyDescription { get; set; }
// [DataType(DataType.Date)]
public System.DateTime? CreatedDate { get; set; }
//[DataType(DataType.Date)]
public System.DateTime? UpdatedDate { get; set; }
public int CreatedUserId { get; set; }
public bool IsActive { get; set; }
public bool Status { get; set; }
public virtual ICollection<SurveyQuestionMetadata> SurveyQuestionMetadatas { get; set; }
public virtual ICollection<SurveyCustomerMetadata> SurveyCustomerMetadatas { get; set; }
public string Token { get; set; }
}
GetData Ajax Event
// GET: Survey
public ActionResult GetData()
{
using (MerinosSurveyEntities entity = new MerinosSurveyEntities())
{
List<Surveys> surveys = entity.Surveys.Where(x => x.IsActive && x.Status)
.OrderBy(x => x.SurveyId).ToList();
return Json(new { data = surveys }, JsonRequestBehavior.AllowGet);
}
}
How I should change my GetData event.And what list should go to the client side??
Best Practice is, use ViewModel[Not Entity/Model classes] to manipulate / play at Client Side.
So use ViewModel, Inherit Model classes and then use Annotations
For eg.
Public class ViewModelClass: ModelClass
{
[Required("First Name is Required")]
Public String FirstName {get; set;}
}
For do such thing you can use partial classes and use "ModelMetadataType" in .net core annotation above your class.
lets do it in code:
this is your model that is created in edmx:
public partial class Student{
public string FirstName {get; set;}
}
first of all you have to create a partial class in another file with same name as student class and be careful its name space should be same as above class. (classes must be out of edmx file)
[ModelMetadataType(typeof(StudentMetaData))]
public partial class Student{
}
and at the end you must create your metadata class like this:
public class StudentMetaData{
[Display(name="First Name")]
public string FirstName {get; set;}
}
now you can update your edmx file without changing the data annotations in your metadata classes.
https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.dataannotations.metadatatypeattribute?view=netframework-4.8
Working from memory at the moment, but the EF classes are always partial so create another partial implementation of the same class, then add the Interface and Metadatatype binding to that.
// Entity Framework Model
public partial class User
{
public string Email { get; set; }
public string Password { get; set; }
}
// Your Interface with data annotations
public interface IUser
{
[Required]
string Email { get; set; }
[Required]
string Password { get; set; }
}
// Partial Model appling the interface to the entity model
[MetadataType(typeof(IUser))]
public partial class User : IUser
{
}
Under this approach, in the future, you only need to worry about updating your interface should you add new properties
Copy the generated CS files (the one's with your table names) that you've already added your annotations to, to another folder, then overwrite the newly generated ones, I do it this way and shall continue to until there's a more hassle-free way to do it.
As a newbie with ASP.NET MVC pattern, I'm trying to create a small web application in order to practice knowledge learned through some tutorials.
I have some obscure things about Model and ViewModel. I understand that Model defined only the table structure whereas ViewModel defined the logic for data, How to handle data... Furthermore, ViewModel is used when I want to display more than one model into my View.
Well, it's very theoretical and I'm trying to develop this with my application.
My application:
This application lets to handle projects and people. I can create a new project object containing some properties: project name, project location, ... and add a list of people who will work on this specific project.
Then, in the other side, I have a simple people table with properties like : Firstname, Lastname and function.
When I create a new project, I would like to select one or multiple people in order to attach them to the project.
My class People:
I created a simple class which looks like this:
public class People
{
public int PeopleID{ get; set; }
public string Lastname { get; set; }
public string Firstname { get; set; }
public string Job{ get; set; }
}
I removed Annotations in order to see clearer my class.
I created the CRUD associated and it works fine.
My class Project:
In this class, I define properties from project object and I would like add a list of people collaborating on the project.
I have:
public class Project
{
public int ProjectID { get; set; }
public string ProjectName{ get; set; }
public string ProjectLocation{ get; set; }
public List<People> ListOfPeople { get; set; }
}
If I understand, now I have to create a ViewModel in order to create my Project object with information from Project and People classes ?
My class ProjectPeopleVM:
This class is identical as Project class ?
So I have:
public class ProjectPeopleVM
{
public int ProjectID { get; set; }
public string ProjectName{ get; set; }
public string ProjectLocation{ get; set; }
public List<People> ListOfPeople { get; set; }
}
Is it right ? I have some doubts about this.
If I want to create a controller class which let to Create a new object Project, I have to fill the ListOfPeople by using EF ? Something like db.People.ToList() ?
public class ProjectsController : Controller
{
private MyAppContext db = new MyAppContext();
public ActionResult Create()
{
var people_list = db.People.ToList();
var project = new ProjectPeopleVM
{
ListOfPeople = people_list;
// What I need to add here ? Data to populate ListOfPeople come from people_list variable
}
return View(project);
}
I'm a bit lost.
It's not necessary that you create a duplicate of your class just to see the information but it seems that in your code, you might need to because;
I noticed that in your Project Model, you didn't use public virtual List<People> or the virtual keyword, which is used for "lazy loading". When an existing project is taken from the db context, if you have the virtual keyword on your property, then it would automatically load the associated object. On the other hand, if you don't have it, then you will need to manually assign the list. Using lazy loading might have a little effect on the performance but with this you can view the properties of your child class immediately.
If your list has virtual property,
public class Project
{
public int ProjectID { get; set; }
public string ProjectName{ get; set; }
public string ProjectLocation{ get; set; }
public virtual List<People> ListOfPeople { get; set; }
}
Then in your controller or view, you could navigate to the properties of the objects in that list;
// this will give the first name of the first person on the first project
db.Project.FirstOrDefault().ListOfPeople.FirstOrDefault().FirstName;
For your create action in your controller, since it's a new Project, it doesn't have any People in it. Hence you will need to manually populate that list. To populate it, since you only need specific people, I suggest to use a checkbox or multiple input fields (aided with javascript).
The ListOfPeople can be populated by having a form element;
<input name="ListOfPeople[1].PeopleId" value="1"/>
<input name="ListOfPeople[1].FirstName" value="Mark"/>
<input name="ListOfPeople[1].LastName" value="Jacob"/>
<input name="ListOfPeople[1].PeopleId" value="2"/>
<input name="ListOfPeople[2].FirstName" value="Red"/>
<input name="ListOfPeople[2].LastName" value="Wandersee"/>
When you submit the form, the values will be bound to the Project model's ListOfPeople. Then that's the time you will need to loop through it and create a ProjectPerson (junction) record which determines where this person belongs to.
foreach(var i in model.ListOfPeople){
ProjectPerson pp = new ProjectPerson();
... // do property assignment
db.ProjectPerson.add(pp);
}
your view models should be used to map a combination of data drawn from the db. i.e.
public class Project
{
public int ProjectID { get; set; }
public string ProjectName{ get; set; }
public string ProjectLocation{ get; set; }
public IColleciton<People> ListOfPeople { get; set; }
}
public class People
{
public int Id{ get; set; }
public string Name{ get; set; }
public virtual Project project { get;set; }
}
this will allow relational retrieval from EF
viewModel should be used when you need a combination of this data without relationship i.e.
public class Project
{
public int ProjectID { get; set; }
public string ProjectName{ get; set; }
public string ProjectLocation{ get; set; }
}
public class People
{
public int Id{ get; set; }
public string Name{ get; set; }
}
public class ProjectVm
{
public int ProjectID { get; set; }
public string ProjectName{ get; set; }
public string ProjectLocation{ get; set; }
public ICollection<People> ListOfPeople { get; set; }
}
you can use a tool such as automapper to set up the mapping between objects which will generate custom model inside controller.
see this article: http://bengtbe.com/blog/2009/04/14/using-automapper-to-map-view-models-in-asp-net-mvc/
and DB Relationships
https://learn.microsoft.com/en-us/ef/ef6/modeling/code-first/conventions/built-in
I am creating some view models for my ASP MVC web app.
I created "code first" models for database. Is it a good way to derive view models from database models?
Example database model:
public class Project
{
[Key]
public int Id { get; set; }
public int? CustomerId { get; set; }
public int TypeId { get; set; }
public string Number { get; set; }
public string Name { get; set; }
}
View model:
public class ViewModelProject : Project
{
[NotMapped]
public DateTime? Start { get; set; }
[NotMapped]
public DateTime? End { get; set; }
[NotMapped]
public string Manager { get; set; }
}
Is this the right way or is it completely false?
EDIT (subquestion):
I have some very simple database models like ProjectType, which only contains i.e. two properties. Should I also fragment those models in model view or can I make it that way:
Simple database model:
public class ProjectType
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public int? Code { get; set; }
}
Can I use it like so:
public class ProjectVM
{
public string Name { get; set; }
public int Number { get; set; }
public ProjectType Type { get; set; }
}
Or does it have to be fragmented like so:
public class ProjectVM
{
public string Name { get; set; }
public int Number { get; set; }
public string Type { get; set; }
public int TypeCode { get; set; }
}
I would not recommend doing it this way. I (and many others) have tried it and it doesn't work well. You will inadvertedly run into troubles, since an MVC model has to be tailored to the view and what you get from the DB rarely fits. Sure, you can hammer it into place, but the code quickly gets messy and store-related and UI code starts to mangle together. This even shows in your example, since you have to put the NotMappedAttribute (which is related to data storage), to ViewModelProject (a class at UI level).
There are many other examples to show this problem, but an especially good one I find when you want to serialize a model object to JSON and send it to a JavaScript client. The JSON serializer takes the values of all public properties and adds them to the JSON. If you want to exclude a property, you have to mark it with a ScriptIgnoreAttribute, which you would also have to apply to the base class, which breaks separation between UI and store-related code.
The better way to go is to keep the staorage model and the MVC model separated and to map the data from one to the other (there are already pre-existing frameworks that help you with that, such as Automapper). This comes with additional advantages, for example better testability, since you are now not dependent on a specific data store to create model instances.
I am learning how to use MVC right now and I just have a question on when I am creating and updating entries in the database. I was reading a post from this page: asp.mvc 4 EF ActionResult Edit with not all fields in view
The guy in it said to create a model that will be used, so is the efficient way to insert a new row and update an existing row by having two models with different properties?
So my models would look like this -
public class UserModelView
{
public string FirstName { get; set; }
public string Surname { get; set; }
public DateTime AccountCreated { get; set; }
public DateTime? LastLoggedIn { get; set; }
}
public class UserModelCreate
{
[Key]
public int UserId { get; set; }
public string FirstName { get; set; }
public string Surname { get; set; }
public DateTime AccountCreated { get; set; }
}
public class UserModelUpdate
{
public string FirstName { get; set; }
public string Surname { get; set; }
public DateTime? LastLoggedIn { get; set; }
}
Is this the best way to do what I need to do?
Im guessing you were previously using the entity class when binding your model back in.
You shouldn't do that!
The guy in the post is right, this is a much better way of controlling your entity and model information and provides a layer of seperation between the two.
After all you wouldnt want a user being able to directly manipulate an entity via a HTTP request.
I answered something similar here
I have a database and I'm accessing it via EF.
public partial class Project
{
public int ProjectID { get; set; }
public string Name { get; set; }
public virtual ICollection<ProjectAssets> ProjectAssets { get; set; }
}
public partial class ProjectAssets
{
public int MappingID { get; set; }
public int ProjectID { get; set; }
public int AssetID { get; set; }
public virtual Project Project { get; set; }
public virtual Asset Asset { get; set; }
}
public partial class Asset
{
public int AssetID { get; set; }
public string Name { get; set; }
public short Type { get; set; }
public virtual ICollection<ProjectAssets> ProjectAssets { get; set; }
}
So, my program have only 1 active Project in the time.
I want to be able to bind to Project and display as a tree or some other way all Assets and I want to be able to create new Asset or add existing Asset what belongs to other project.
If I will use the generated entities I would not be able to manage that all so I need some rules. I've already found good impl. of repositories, but still don't know how to create rules.
Do I need to create something like:
public class WorkProject : Project
{
public WorkProject(Project projject){...}
WorkAsset CreateAsset(){...}
void AddAsset(Asset asset){...}
}
As far as I understand your question, you want to control the graph of entities which are related to a project object. You can leave the repository layer intact and put another layer (business layer) on top of it to enforce the rules.