When I'm trying to add a view for edit data reason, it gives me the error No parameterless constructor defined for this object
This is my controller:
public class MyNewPageController : Controller
{
MyNewPageController c = new MyNewPageController();
public MyNewPageController()
{
}
public IActionResult Index(PedroJorge.DAL.ProductDAL pd)
{
List<CS_mostrarModel> pList = new List<CS_mostrarModel>(pd.Read());
return View("~/Views/MyNewPage/Index.cshtml", pList);
}
public ActionResult Edit(int ID)
{
List<CS_mostrarModel> pList = new List<CS_mostrarModel>();
//Get the student from studentList sample collection for demo purpose.
//You can get the student from the database in the real application
var std = pList.Where(s => s.ID == ID).FirstOrDefault();
return View(std);
}
[HttpPost]
public ActionResult Edit(Product std)
{
//write code to update student
return RedirectToAction("Index");
}
}
public class SampleContext : DbContext
{
public DbSet<Order> Orders { get; set; }
public SampleContext(DbContextOptions<SampleContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Order>().ToTable("Order");
}
}
Model:
public class CS_mostrarModel
{
public int ID { get; set; }
public string ProductName { get; set; }
[Display(Name = "Release Date")]
[DataType(DataType.Date)]
public DateTime Date { get; set; }
[Column(TypeName = "decimal(18, 2)")]
public int Price { get; set; }
public int PersonsNumber { get; set; }
public string TourType { get; set; }
public int CarsNumber { get; set; }
}
I don't know what is wrong and I already tried everything that I saw in internet, so if someone know how to fix this please help!
Unless that is a typo, then chances are that having the controller creating an instance of itself in a local field is causing a stack overflow exception when the framework is trying to activate the controller.
Each instance will try to create another instance until you run out of space on the stack.
In previous versions, the exception thrown when creating a controller was swallowed by the framework and the standard unhelpful
No parameterless constructor defined for this object
message was thrown.
Remove
MyNewPageController c = new MyNewPageController();
from the controller and it should be able to be initialized when requested.
Related
I am trying to implement a method where I select all records that belong to the correct StateId (NJ, DE, PA); I am using dependency injection and the repository design pattern which I am new to.
Here is what I have in my controller:
private IWorkOrderRepository _workOrderRepository;
public DependencyInjectionController(IWorkOrderRepository workOrderRepository)
{
_workOrderRepository = workOrderRepository;
}
public IActionResult WorkOrders()
{
var model = _workOrderRepository.GetWorkOrders();
return View(model);
}
public IActionResult Nj(string LocationFilter)
{
var locations = _workOrderRepository.GetWorkOrders().Select(x => x.StateId == LocationFilter).ToList();
return View(locations);
}
The GetWorkOrders method works exactly as it's supposed to.
Here is my Model:
public class WorkOrderContext : DbContext
{
public DbSet<WorkOrder> WorkOrder { get; set; }
public WorkOrderContext(DbContextOptions<WorkOrderContext> options)
: base(options)
{
}
}
public class WorkOrder
{
[Key]
public int UserId { get; set; }
public string LocationId { get; set; }
public string Reason { get; set; }
public bool IsActive { get; set; } = true;
public DateTime Date { get; set; } = DateTime.Now;
public string StateId { get; set; }
}
The error I am getting when I hit the route is:
"The model item passed into the ViewDataDictionary is of type 'System.Collections.Generic.List1[System.Boolean]', but this ViewDataDictionary instance requires a model item of type 'System.Collections.Generic.IEnumerable1[WorkOrderServices.Models.WorkOrder]'."
Select is transforming the list of work orders to booleans: true where the StateId matches the location filter, and false where it doesn't.
Instead of transforming the list, you want to filter it with Where: Where(x => x.StateId == LocationFilter).
I'm trying to do the Entity Framework Code First Approach. I made my models then the DbContext and added it to the controller. I followed an online tutorial as I've never used C# before.
However the tables don't create until I add a call to the db in the controller.
public ActionResult Index()
{
db.posts.ToList();
return View();
}
The call however throws.
InvalidOperationException: The class 'SocialMediaMining.Models.SocialMedia.Facebook.posts' has no parameterless constructor.
posts class:
public class posts
{
public dynamic jsonObj { get; set; }
public posts(dynamic json)
{
jsonObj = json;
if (jsonObj != null)
{
id = jsonObj.id;
name = jsonObj.name;
if(jsonObj.feed !=null)
{
feed = new feed(jsonObj.feed);
}
}
}
public string id { get; set; }
public string name { get; set; }
public virtual feed feed { get; set; }
public int postsId { get; set; }
}
The controller:
public class FacebookController : Controller
{
//The dbcontext call
FacebookEntities db = new FacebookEntities();
public ActionResult Index()
{
// the error
db.posts.ToList();
return View();
}
// more code here
}
//DbContext
public class FacebookEntities : DbContext
{
public FacebookEntities() : base("SocialMediaDb")
{
}
public DbSet<posts> posts { get; set; }
//more code here
}
Any help is appreciated
The exception message is pretty straightforward - you need to specify a parameterless constructor for posts class, which should look like this:
public class posts
{
// add this constructor
public posts()
{
}
public dynamic jsonObj { get; set; }
public posts(dynamic json)
{
jsonObj = json;
if (jsonObj != null)
{
id = jsonObj.id;
name = jsonObj.name;
if(jsonObj.feed !=null)
{
feed = new feed(jsonObj.feed);
}
}
}
public string id { get; set; }
public string name { get; set; }
public virtual feed feed { get; set; }
public int postsId { get; set; }
}
Note that any entity class which want to be included in DbSet<T> type parameter must have parameterless constructor to enable binding with EF. Also it is recommended to use PascalCase for entity class names and property names, e.g. Posts.
I am trying to create a sample validation attribute to learn more about MVC. I have created the validation attribute, but when I run the application the validation attribute is called twice -> before calling the controller and before saving the DBContext. I believe this should be called only once. Can you guide me where am I doing wrong.
Validation Attribute: I am trying to validate whether the property has too many words than the specified maxWords
public class ValidationEx : ValidationAttribute
{
int _maxWords = 1;
public ValidationEx()
: base("{0} has more too many words")
{
_maxWords = 1;
}
public ValidationEx(int maxWords):base("{0} has more too many words")
{
_maxWords = maxWords;
}
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
if (value != null)
{
string data = value as string;
if (data.Split(' ').Length > _maxWords)
{
var errorMessage = FormatErrorMessage(validationContext.DisplayName);
return new ValidationResult(errorMessage);
}
}
return ValidationResult.Success;
}
}
Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Album album)
{
if (ModelState.IsValid)
{
db.Albums.Add(album);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.GenreID = new SelectList(db.Genres, "GenreID", "Name", album.GenreID);
ViewBag.ArtistID = new SelectList(db.Artists, "ArtistID", "ArtistName", album.ArtistID);
return View(album);
}
Note: Validation is fired before reaching controller and while executing db.SaveChanges()
Model:
public class Album
{
public virtual int AlbumID { get; set; }
public virtual int GenreID { get; set; }
public virtual int ArtistID { get; set; }
[Required(ErrorMessageResourceType= typeof(ErrorMessages), ErrorMessageResourceName="TitleRequired")]
[Display(Name="Movie Name")]
[ValidationEx()]
public virtual string Title { get; set; }
[Range(0,1000)]
public virtual decimal Price { get; set; }
public virtual string AlbumArtUrl { get; set; }
public virtual Genre Genre { get; set; }
public virtual Artist Artist { get; set; }
[StringLength(40)]
public virtual string Description { get; set; }
}
DBContext
public class MusicAlbumStoreDBContext : DbContext
{
// You can add custom code to this file. Changes will not be overwritten.
//
// If you want Entity Framework to drop and regenerate your database
// automatically whenever you change your model schema, add the following
// code to the Application_Start method in your Global.asax file.
// Note: this will destroy and re-create your database with every model change.
//
// System.Data.Entity.Database.SetInitializer(new System.Data.Entity.DropCreateDatabaseIfModelChanges<MusicAlbumProject.Models.MusicAlbumStoreDBContext>());
public MusicAlbumStoreDBContext() : base("name=MusicAlbumStoreDBContext")
{
}
public DbSet<Album> Albums { get; set; }
public DbSet<Genre> Genres { get; set; }
public DbSet<Artist> Artists { get; set; }
public DbSet<Order> Orders { get; set; }
}
You are using the same class as model and as view model. There is a reason why MVC distringuishes between these 2 types. You really should add a separate model and a separate view model class.
IsValid() is called twice
before the controller action as the data is validated before the action is called
on db.SaveChanges() because the DB Context also does a validation
The profile:
public class StudentProfile : Profile
{
protected override void Configure()
{
Mapper.CreateMap<Student, StudentIndexModel>();
}
}
And the line it breaks on:
public ActionResult Index()
{
// Breaks here
var students = Mapper.Map<IEnumerable<StudentIndexModel>>(db.Students.ToList());
return View(students);
}
I'm getting an unsupported mapping exception when it gets records from the database. No exception when there are no records returned (the table has no records)
Error
Missing type map configuration or unsupported mapping.
Mapping types:
Student -> StudentIndexModel
ContosoUniversity.Models.Student -> ContosoUniversity.ViewModels.StudentIndexModel
Destination path:
IEnumerable`1[0]
The student class:
public class Student : Entity
{
public Student() { }
public string LastName { get; set; }
public string Forenames { get; set; }
public DateTime EnrolmentDate { get; set; }
public virtual ICollection<Enrolment> Enrolments { get; set; }
}
And the StudentIndexModel class:
public class StudentIndexModel
{
public int Id { get; set; }
public string LastName { get; set; }
public string Forenames { get; set; }
public DateTime EnrolmentDate { get; set; }
}
Where am I going wrong?
I've done it again, I find the answer to my own question 2 seconds later.
I added this to the Global.asax:
AutoMapperConfiguration.Configure();
Where AutomapperConfiguration has the Mapper.Initialize() method
I have a model like the following:
public class TestViewModel
{
string UpdateProperty { get; set; }
string IgnoreProperty { get; set; }
ComplexType ComplexProperty { get; set; }
}
where
public class ComplexType
{
long? Code { get; set; }
string Name { get; set; }
}
My controller action:
public Edit(int id, FormColleciton formCollection)
{
var model = service.GetModel(id);
TryUpdateModel(model);
//...
}
When calling the Edit action I have a formCollection parameter containing only a key/value for UpdateProperty.
After the call to TryUpdateModel UpdateProperty is set correctly, IgnoreProperty is left un-touched but ComplexProperty is set to null, even if it previously had a value.
Should TryUpdateModel() only modify properties that are a part of the request? If this is not the case what is the best way to work around this so ComplexProperty is only modified if it is included in the request?
After it was pointed out by Darin that the test case above didn't demonstrate the problem I have added a scenario where this problem really occurs:
public class TestViewModel
{
public List<SubModel> List { get; set; }
}
public class SubModel
{
public ComplexType ComplexTypeOne { get; set; }
public string StringOne { get; set; }
}
public class ComplexType
{
public long? Code { get; set; }
public string Name { get; set; }
}
Controller Action:
public ActionResult Index()
{
var model = new TestViewModel
{
List = new List<SubModel> {
new SubModel{
ComplexTypeOne = new ComplexType{Code = 1, Name = "5"},
StringOne = "String One"
}
}
};
if (TryUpdateModel(model)) { }
return View(model);
}
Sending this request:
/Home/Index?List[0].StringOne=test
updates SubModel.StringOne property but sets ComplexTypeOne to null, even though it is not included in the request.
Is this expected behaviour (given this does not happen unless an enumerable of complex types is used)? How best to work around this?
There must be something wrong with your test case as I was unable to reproduce it. Here's what I tried:
Model (notice that I use public properties):
public class TestViewModel
{
public string UpdateProperty { get; set; }
public string IgnoreProperty { get; set; }
public ComplexType ComplexProperty { get; set; }
}
public class ComplexType
{
public long? Code { get; set; }
public string Name { get; set; }
}
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new TestViewModel
{
IgnoreProperty = "to be ignored",
UpdateProperty = "to be updated",
ComplexProperty = new ComplexType
{
Code = 1,
Name = "5"
}
};
if (TryUpdateModel(model))
{
}
return View();
}
}
Now I send the following request: /home/index?UpdateProperty=abc and inside the condition only the UpdateProperty is modified with the new value from the query string. All other properties, including the complex property, are left untouched.
Also notice that the FormCollection action parameter is useless.