Data Not Saved after click on submit button - MVC 5 - asp.net-mvc

After click on the sumbit button and trying to debug the code i don't recieve any error or exception but the data not saved
I have a class called login ... need the user after click on login button save its data in the database
This is my Post Action:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(Login model, string returnUrl)
{
Context db = new Context();
if (string.IsNullOrEmpty(model.LoginName))
{
this.ModelState.AddModelError("LoginName", "this field is required");
return this.View(model);
}
try
{
if (ModelState.IsValid)
{
var user = new Login { LoginName = model.LoginName, LoginPassword = model.LoginPassword };
db.Logins.Add(user);
db.SaveChanges();
return Redirect("http://www.google.com");
}
else
return View();
}
catch (Exception e)
{
return View();
}
}
And this is my Login Class:
[Table("Login")]
public partial class Login
{
public int ID { get; set; }
[StringLength(50)]
public string LoginName { get; set; }
[StringLength(10)]
public string LoginPassword { get; set; }
}
And this is my DBContext:
public class LoginContext : DbContext
{
public LoginContext () : base("LoginContext ")
{
}
public virtual DbSet<Login> Logins { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
After return to the google link the data not saved.

After trying a lot of solution Finally i found that :
When adding the Code first code i had make the DBContext with the
same name of the table name "Login".
Delete all of them then add the new code first "DBContext" and
choose your DB.
Will find that the DBConext will added automatically and your tables also will added.
That will work correctly.

Related

Save data from modal (popup form) into local database - asp.net mvc

I manage to implement insert function successfully as below. But this one is done by using another view -"Create", Once submit it goes to "ViewSecurityForm" View. But now, I want to implement the insert function using modal in "ViewSecurityForm". I have few modals to be implemented in "ViewSecurityForm" view. Can you help me how to do it?
My method for create function in "Create" view:
public ActionResult Create(ServerInfo alldata)
{
try
{
db.ServerInfos.Add(alldata);
db.SaveChanges();
return RedirectToRoute(new { controller = "Employee", action = "ViewSecurityForm" });
}
catch
{
return View();
}
}
My method for modal in "ViewSecurityForm" view:
public ActionResult ViewSecurityForm()
{
/*What should I write here*/
}
My class:
public class ViewSecurityForm
{
public List<ServerInfo> allServerInfo { get; set; }
public List<NetworkDeviceInfo> allNetworkDeviceInfo { get; set; }
}
public class SecurityContext : DbContext
{
//Create database without name
public SecurityContext ()
{
Database.SetInitializer(new SecurityDBInitializer());
}
//Create Table as below
public DbSet<ServerInfo> ServerInfos { get; set; }
public DbSet<NetworkDeviceInfo> NetworkDeviceInfos { get; set; }
}
My Modal image

Error in adding custom table in user identity system

I was following this article to add my custom table.
http://www.itorian.com/2013/11/customizing-users-profile-to-add-new.html
In My AccountViewModels.cs, i have tried to add new custom table(UserProfileInfo) something like this---
public class ApplicationUser : IdentityUser
{
public string EmailID { get; set; }
public virtual UserProfileInfo UserProfileInfo { get; set; }
}
public class UserProfileInfo
{
public int Id { get; set; }
public string City { get; set; }
public string MobileNum { get; set; }
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection")
{
}
public System.Data.Entity.DbSet<UserProfileInfo> UserProfileInfo { get; set; }
}
}
and in my Account Controller's Register action (Post Version), i have tried to update register action like this but you can see in code at city and mobileNum,
its stating -----
xxx.RegisterViewModel' does not contain a definition for 'City' and no extension method 'City' accepting a first argument of type 'xxx.RegisterViewModel' could be found....
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new ApplicationUser() { UserName = model.UserName, EmailID = model.EmailID,
UserProfileInfo = new UserProfileInfo
{ City = model.City,
MobileNum = model.ModileNum
}
};
var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
await SignInAsync(user, isPersistent: false);
return RedirectToAction("Index", "Home");
}
else
{
AddErrors(result);
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
i dont know what's happening here.plzz help me out.thanks in advance
I have seen that article as u mentioned.You will never be able to pass City and mobile number as parameter as u have not defined them in register view model.
If u simply want to just create and another table and wants to save that into database then u can do it like this-------
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new ApplicationUser() { UserName = model.UserName };
user.HomeTown = model.HomeTown;
var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
await SignInAsync(user, isPersistent: false);
return RedirectToAction("Index", "Home");
}
else
{
AddErrors(result);
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
and change your Dbcontext to something like this----
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection")
{
}
public DbSet<UserProfileInfo> UserProfileInfo { get; set; }
}
and your Application user class should be something like this-----
public class ApplicationUser : IdentityUser
{
public string HomeTown { get; set; }
public virtual UserProfileInfo UserProfileInfo { get; set; }
}
You've created separated table - UserProfileInfo - that isn't part of ApplicationUser one.
What you've to do is:
crate new ApplicationUser
create new UserProfileInfo
link each other with proper navigation property or assign foreign keys manually (depending on your configuration)

how to save and update a record in the same form using mvc viewmodel

public int ID { get; set; }
[Required]
public string Surname{get;set;}
[Required (ErrorMessage="FirstName Required")]
public string Firstname{get;set;}
[Required(ErrorMessage="please enter your OtherNames")]
public string Othername{get;set;}
[Required(ErrorMessage="please enter your sex")]
public string Sex{get;set;}
[Required (ErrorMessage="please enter your DateOfBirth")]
public DateTime DateOfBirth{get;set;}
[Required(ErrorMessage="Address is required")]
public string Address{get;set;}
[Required(ErrorMessage="city is required")]
public string City{get;set;}
[Required(ErrorMessage="State is required")]
public string State{get;set;}
public string Country{get;set;}
}
i have created an interface which acts as the middleman between my Domain Layer and my WEBUI
public interface IStudentRepository
{
IQueryable<Student> Student { get; }
//we using a method to save the record into our database
void Save(Student student);
}
the interface is being implented by my repository class which perfoms all the actions of saving the records into the database and retrieving it..
public class EFRepository:IStudentRepository
{
private EFDBContext context = new EFDBContext();
public IQueryable<Student> Student{ get { return context.Students; } }
public void Save(Student student)
{
if (student.ID == 0)
{
context.Students.Add(student);
}
context.SaveChanges();
}
and then i have a view which creates an instance of the student class and uses the interface to store the records in the database, which works perfectly..
[HttpPost]
public ActionResult Registration(Student student)
{
if (ModelState.IsValid)
{
studentrepository.Save(student);
}
return View(student);
}
this works perfectly for me..
But i want to be able to update this same fields incase the student make changes to the fields and it should overwrite the existing record in the database.
i have seen my tutorials where the student id number is passed as an action link before it overwrites the existing record.
however,what i want is the ability for the student to edit the same form using the same button and the same view being display.any help would be appreciated.
You just need to change you repository method to look something like this:
public class EFRepository:IStudentRepository
{
private EFDBContext context = new EFDBContext();
public IQueryable<Student> Student{ get { return context.Students; } }
public void Save(Student student)
{
if (student.ID == 0)
{
context.Students.Add(student);
}
else
{
Student existingStudent = context.Students.FirstOrDefault(x => x.ID == student.ID);
if(existingStudent != null)
{
context.Entry(existingStudent).CurrentValues.SetValues(student);
context.Entry(existingStudent).State = System.Data.Entity.EntityState.Modified;
}
}
context.SaveChanges();
}
or you can use the Entity Framework Attach method as this will automatically track the object state and update the details

Help improving (refactoring) my code. Automapper - EF - asp.net mvc-3

I have this 4 models - 2 Domain Models and 2 DTOs
public class Project
{
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<Task> Tasks { get; set; }
}
public class Task
{
public int ID { get; set; }
public virtual int ProjectID { get; set; }
public string Name { get; set; }
public virtual Project Project { get; set; }
}
public class ProjectDTO
{
[Required]
public string Name { get; set; }
public List<TaskDTO> Tasks { get; set; }
}
public class TaskDTO
{
[Required]
public string Name { get; set; }
public int ID { get; set; }
public bool MarkRemove { get; set; }
}
Heres my automapper configuration
Mapper.CreateMap<Project, ProjectDTO>();
Mapper.CreateMap<ProjectDTO, Project>().ForMember(p =>p.ID, opt=>opt.Ignore()).ForMember(p=>p.Tasks, opt=>opt.Ignore());
Mapper.CreateMap<Task, TaskDTO>();
Mapper.CreateMap<TaskDTO, Task>().ForMember(task=>task.ProjectID, opt=>opt.Ignore()).ForMember(task=>task.Project, opt=>opt.Ignore());
Heres my HttpPost Edit action
[HttpPost]
public ActionResult Edit(int id, ProjectDTO p)
{
if (ModelState.IsValid)
{
var dbProject = db.Projects.Where(pr => pr.ID == id).Single();
Mapper.Map(p, dbProject);
foreach (var task in p.Tasks)
{
Task dbTask;
try
{
dbTask = dbProject.Tasks.Where(t => t.ID == task.ID).Single();
}
catch
{
dbTask = new Task();
Mapper.Map(task, dbTask);
dbProject.Tasks.Add(dbTask);
}
if (task.MarkRemove)
{
db.Tasks.Remove(dbTask);
}
else {
Mapper.Map(task, dbTask);
}
}
db.Entry(dbProject).State = EntityState.Modified;
db.SaveChanges();
TempData["Success"] = "Modelo Valido";
return RedirectToAction("Index");
}
return View(p);
}
Im not completely happy with this but I dont think there is a much cleaner approach to handling this somewhat complex scenario....
now that it is working I would like to at least refactor this to use repository pattern or something in a way that the controller action is not that convoluted.. this will eventually be production code :s
can anyone give me some advice on how to refactor this?
please help.
I would use a service layer, like this:
public interface IProjectsService
{
void RemoveTasks(int projectId, IEnumerable<int> taskIdsToRemove);
}
and then the controller would depend on this service layer:
public class ProjectsController : Controller
{
private readonly IProjectsService _service;
public ProjectsController(IProjectsService service)
{
_service = service;
}
public ActionResult Edit(int id)
{
// TODO: Add methods to your service layer
// allowing to retrieve projects, then map
// the resulting project into a view model
throw new NotImplementedException();
}
[HttpPost]
public ActionResult Edit(int id, ProjectDTO p)
{
if (!ModelState.IsValid)
{
return View(p);
}
var taskIdsToRemove = p.Tasks.Where(x => x.MarkRemove).Select(x => x.ID);
_service.RemoveTasks(id, taskIdsToRemove);
TempData["Success"] = "Modelo Valido";
return RedirectToAction("Index");
}
}
This way the controller logic is more weakly coupled to the way we do data access. That's an implementation detail that a controller should never have to worry about.
As a further improvement to the RemoveTasks method you could make it return a boolean indicate the success or failure of the operation along with an error message so that the Edit action could redisplay the view and show the error in case something goes wrong.
Now as far as this service layer is concerned, the RemoveTasks method is a business operation that could be built upon multiple CRUD operations with some repository. So this service layer would itself depend on a repository. It is only this repository that will have to know about EF or whatever you are using to do your data access.
So basically everytime I see someone asking a question about ASP.NET MVC and EF at the same time, for me, those are two completely different questions. ASP.NET MVC should not know anything about EF. EF should be buried away behind an abstraction of a repository.
I realize this question has been inactive for a while, but I had the same problem, and though I would post my solution for anyone else struggling with the nested model not being saved during edit.
[HttpPost]
public ActionResult Edit(ProjectDTO p)
{
if (ModelState.IsValid)
{
// *****MODIFIED CODE HERE********
for (int i = 0; i < p.Tasks.Count; i++)
{
db.Entry(p.Tasks[i]).State = EntityState.Modified;
}
// *************************************
db.Entry(dbProject).State = EntityState.Modified;
db.SaveChanges();
TempData["Success"] = "Modelo Valido";
return RedirectToAction("Index");
}
return View(p);
}
Basically, you want to set State of each nested model to Modified as well as the root model.

ASP.NET EditorTemplate DropdownList

Every time I add a new App It creates a new AppCategory. I am seriously screwing this up somehow
code first entity framework objects
public class AppCategory
{
public int ID { get; set; }
public string Name { get; set; }
public ICollection<App> apps { get; set; }
}
public class App
{
public int ID { get; set; }
public string Name { get; set; }
public AppCategory Category { get; set; }
}
Editor Template (I would love to just make just one Foreign Key EditorTemplate)
#inherits System.Web.Mvc.WebViewPage
#Html.DropDownList("Category", LIG2010RedesignMVC3.Models.Repo.GetAppCategoriesSelect())
and of course the repository
public static IEnumerable<SelectListItem> GetAppCategoriesSelect()
{
return (from p in GetAppCategories()
select new SelectListItem
{
Text = p.Name,
Value = p.ID.ToString(),
});
}
public static ICollection<AppCategory> GetAppCategories()
{
var context = new LIGDataContext();
return context.AppCategories.ToList();
}
Every time I add a new App It creates a new AppCategory I am seriously screwing this up somehow
Adding more debug info
#inherits System.Web.Mvc.WebViewPage
#Html.DropDownList("", LIG2010RedesignMVC3.Models.Repo.GetAppCategoriesSelect())
gives me a validation message on the post
Parameters application/x-www-form-urlencoded
Category 1
Name 8
Validation error The value '1' is invalid.
This makes sense because Category should be an object not an integer.
Controller Code as asked for
pretty sure this isnt the problem as it came from MVCScaffold
[HttpPost]
public ActionResult Create(App d)
{
if (ModelState.IsValid)
{
context.Apps.Add(d);
context.SaveChanges();
return RedirectToAction("Index");
}
return View();
}
My model was incorrectly set up ... virtual ICollection and just the foreign key id for the sub and everything worked... changes below
Model
public class AppCategory
{
public int ID { get; set; }
public string Name { get; set; }
public **virtual** ICollection<App> Apps { get; set; }
}
public class App
{
public int ID { get; set; }
********************************************
[UIHint("AppCategory")]
public int AppCategoryID { get; set; }
********************************************
public string Name { get; set; }
}
public class LIGDataContext : DbContext
{
public DbSet<AppCategory> AppCategories { get; set; }
public DbSet<App> Apps { get; set; }
}
/Views/Shared/EditorTemplates/AppCategory.cshtml
#inherits System.Web.Mvc.WebViewPage
#Html.DropDownList("", LIG2010RedesignMVC3.Models.Repo.GetAppCategoriesSelect())
AppController
[HttpPost]
public ActionResult Create(App d)
{
if (ModelState.IsValid)
{
this.repository.Add(d);
this.repository.Save();
return RedirectToAction("Index");
}
return View();
}
If you bind your dropDownList to Category.Id, you'll at least get the selected value into that filed, but nothing else in your Category Object.
The model binder cannot create the AppCategory object from the form collection in your Create action because the form only has an ID for that object (the other properties of AppCategory are not there).
The quickest solution would be setting the Category property of your App object manually, like this :
[HttpPost]
public ActionResult Create(App d) {
int categoryId = 0;
if (!int.TryParse(Request.Form["Category"] ?? String.Empty, out categoryId) {
// the posted category ID is not valid
ModelState.AddModelError("Category",
"Please select a valid app category.")
} else {
// I'm assuming there's a method to get an AppCategory by ID.
AppCategory c = context.GetAppCategory(categoryID);
if (c == null) {
// couldn't find the AppCategory with the given ID.
ModelState.AddModelError("Category",
"The selected app category does not exist.")
} else {
// set the category of the new App.
d.Category = c;
}
}
if (ModelState.IsValid)
{
context.Apps.Add(d);
context.SaveChanges();
return RedirectToAction("Index");
}
return View();
}

Resources