Adding values to the controller action manually - asp.net-mvc

I have a model class that is below
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;
namespace MyForms.Models
{
public class Master
{
public int ID { get; set; }
public string ModuleName { get; set; }
public int CreatedBy { get; set; }
public DateTime CreatedDate { get; set; }
public int ModifyBy { get; set; }
public DateTime ModifyDate { get; set; }
public Boolean IsActive { get; set; }
public Boolean IsDeleted { get; set; }
// public virtual ICollection<MasterModule> MasterModules { get; set; }
}
Here in this code I am passing the values through views(textboxes). What are my expections
Module Name is entered through text box and when submit button is clicked
CreatedBy contains the ID of the person who create the module(e.g 1. admin 2. manager)
Created date is automatically added as current Date when submit is clicked
ModifyBy contains the ID of the person who modify (edit) the module(e.g 1. admin 2. manager)
ModifyDate is the curent date when the module is edited
when the module is created is activated always sets to be true.
2 to 6 are settled with coding. Now I want to know how can I handle each situation separetaly.
Currently I am adding all the values manually, I mean through the input box and checkboxes
namespace MyForms.Controllers
{
public class MasterController : Controller
{
//
// GET: /Master/
public ActionResult Index()
{
using (MyFormDemoContext context = new MyFormDemoContext())
{
return View(context.MasterForms.ToList());
}
// return View();
}
public ActionResult Create()
{
return View();
}
[HttpPost]
public ActionResult Create(Master master)
{
try
{
using (MyFormDemoContext context = new MyFormDemoContext())
{
context.MasterForms.Add(master);
context.SaveChanges();
}
return RedirectToAction("Index");
}
catch
{
return View();
}
}
}
}

Related

ASP:NET MVC Summary of a field as a validation for the field itself (Recursiveness)

I Have the following class in a model:
public partial class OrganizationUnit
{
public string code{ get; set; }
public int OrganizationCod { get; set; }
public string name { get; set; }
public string ParentUnitCode{ get; set; }
public int level{ get; set; }
public string author{ get; set; }
public System.DateTime CreateDtStmp{ get; set; }
public int Status { get; set; }
public decimal weighing { get; set; }
[ForeignKey("status")]
public virtual Status UnitStatus { get; set; }
public virtual Organization Organization { get; set; }
public virtual ICollection<OrganizationUnit> OrganizationUnit1{ get; set; }
[ForeignKey("ParentUnitCode")]
public virtual OrganizationUnit OrganizationUnit2{ get; set; }
public OrganizationUnit ()
{
CreateDtStmp= DateTime.Now;
author = HttpContext.Current.User.Identity.Name.Substring(4,HttpContext.Current.User.Identity.Name.Length - 4);
}
}
Before inserting a new record I need to validate sum(weighing) can not exceed 100 including the attempted new record, considering only the records with the same ParentUnit.
Can this be done in the model or should it be done in the controller?
this is the saving controller part (basically is what is autogenerated by VS),consider that the view will send the corresponding parameter to the method:
private SAIM_IPM_DVContext db = new SAIM_IPM_DVContext();
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(OrganizationUnit organizationunit)
{
if (ModelState.IsValid)
{
db.OrganizationUnit.Add(organizationunit);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(organizationunit);
}
If OrganizationUnit1 is the collection of all other units with the same ParentUnit, you can perform the check in the ViewModel by implementing IValidatableObject:
using System.ComponentModel.DataAnnotations;
public partial class OrganizationUnit : IValidatableObject {
/* properties etc... */
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) {
if (OrganizationUnit1.Sum(o => o.weighing) + this.weighing > 100.0) {
yield return new ValidationResult(
"Sum of weightings would exceed 100.",
new[] { "weighing" });
}
}
}
Note that this assumes that the weighing is posted back for all units in the OrganizationUnit1 collection (e.g. as hidden fields) so it is accessible when this check is performed by the MVC pipeline (this is done before your POST action will be hit).
If this check fails, ModelState.IsValid will be false in the controller.
If you have no access to the other units in the Viewmodel, you will have to fetch them from the DB in the controller and perform the check there.
After a while and tries I came up with this solution works perfect, however I am not sure is the best practice. This is on the controller class
public ActionResult Create(OrganizationUnit organizationunit)
{
decimal weighingsum= 0;
foreach (var val in db.OrganizationUnit.Where(t => t.ParentUnitCode== organizationunit.ParentUnitCode))
{
weighingsum+= val.weighing ;
}
weighingsum+= organizationunit.weighing ;
if (weighingsum > 100)
{
ModelState.AddModelError("", "Weighing sum can not exceed 100 for a Parent Unit");
}
else
{
if (ModelState.IsValid)
{
db.OrganizationUnit.Add(organizationunit);
db.SaveChanges();
return RedirectToAction("Index");
}
}
return View(organizationunit);
}
should anyone comes up with a better solution, please do share I'll appreciate it.

how to fetch checkbox value in mvc 4

I am creating mvc4 applicationn using entity framework 5
i am creating a page this contains checkboxes
i created table in db
model class
public class EmpSkillSet
{
public int ID { get; set; }
public string Skill { get; set; }
public bool isSelected { get; set; }
}
}
controller
[HttpPost]
public string AddSkills(IEnumerable<EmpSkillSet> skills)
{
}
How do I create a checkbox in the view?
Then how do i get its value from the database?
By using this example you can fetch only boolen value (True or False)
In view:
#Html.CheckBox("MonOpen", l.MonOpen)
In MOdel:
public class Shop
{
public bool MonOpen { get; set; }
....
}
in controller:
[HttpPost]
public ActionResult ShopCreate(Shop location)
{
Location newShop = new Location();
newShop.MonOpen = location.MonOpen;
....
}

Custom Membership with Microsoft.AspNet.Identity - CreateLocalUser fails

I've been trying to implement a custom version of the new Identity features in ASP.NET 4.5 (Microsoft.AspNet.Identity), using Visual Studio 2013. After many hours of playing around with this, I've simplified my code in an effort to get it running without errors. I've listed my code below. When doing a Local Registration, the database tables are created, but the CreateLocalUser method fails. I'm hoping that someone can help me identify the changes needed.
Models/MembershipModel.cs
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Linq;
using System.Web;
namespace thePulse.web.Models
{
public class PulseUser : IUser
{
public PulseUser() { }
public PulseUser(string userName)
{
UserName = userName;
}
[Key]
public string Id { get; set; }
[Required]
[StringLength(20)]
public string UserName { get; set; }
[StringLength(100)]
public string Email { get; set; }
[Column(TypeName = "Date")]
public DateTime? BirthDate { get; set; }
[StringLength(1)]
public string Gender { get; set; }
}
public class PulseUserClaim : IUserClaim
{
public PulseUserClaim() { }
[Key]
public string Key { get; set; }
public string UserId { get; set; }
public string ClaimType { get; set; }
public string ClaimValue { get; set; }
}
public class PulseUserSecret : IUserSecret
{
public PulseUserSecret() { }
public PulseUserSecret(string userName, string secret)
{
UserName = userName;
Secret = secret;
}
[Key]
public string UserName { get; set; }
public string Secret { get; set; }
}
public class PulseUserLogin : IUserLogin
{
public PulseUserLogin() { }
public PulseUserLogin(string userId, string loginProvider, string providerKey)
{
LoginProvider = LoginProvider;
ProviderKey = providerKey;
UserId = userId;
}
[Key, Column(Order = 0)]
public string LoginProvider { get; set; }
[Key, Column(Order = 1)]
public string ProviderKey { get; set; }
public string UserId { get; set; }
}
public class PulseRole : IRole
{
public PulseRole() { }
public PulseRole(string roleId)
{
Id = roleId;
}
[Key]
public string Id { get; set; }
}
public class PulseUserRole : IUserRole
{
public PulseUserRole() { }
[Key, Column(Order = 0)]
public string RoleId { get; set; }
[Key, Column(Order = 1)]
public string UserId { get; set; }
}
public class PulseUserContext : IdentityStoreContext
{
public PulseUserContext(DbContext db) : base(db)
{
Users = new UserStore<PulseUser>(db);
Logins = new UserLoginStore<PulseUserLogin>(db);
Roles = new RoleStore<PulseRole, PulseUserRole>(db);
Secrets = new UserSecretStore<PulseUserSecret>(db);
UserClaims = new UserClaimStore<PulseUserClaim>(db);
}
}
public class PulseDbContext : IdentityDbContext<PulseUser, PulseUserClaim, PulseUserSecret, PulseUserLogin, PulseRole, PulseUserRole>
{
}
}
Changes to Controllers/AccountController.cs
public AccountController()
{
IdentityStore = new IdentityStoreManager(new PulseUserContext(new PulseDbContext()));
AuthenticationManager = new IdentityAuthenticationManager(IdentityStore);
}
//
// POST: /Account/Register
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
try
{
// Create a profile, password, and link the local login before signing in the user
PulseUser user = new PulseUser(model.UserName);
if (await IdentityStore.CreateLocalUser(user, model.Password))
{
await AuthenticationManager.SignIn(HttpContext, user.Id, isPersistent: false);
return RedirectToAction("Index", "Home");
}
else
{
ModelState.AddModelError("", "Failed to register user name: " + model.UserName);
}
}
catch (IdentityException e)
{
ModelState.AddModelError("", e.Message);
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
As I said above, this implementation fails when the CreateLocalUser method fails (Microsoft.AspNet.Identity.EntityFramework). I cannot figure out why.
The issue here is that IdentityStoreManager has strong dependency on the default implementation of identity EF models. For example, the CreateLocalUser method will create UserSecret and UserLogin objects and save them to stores, which won't work if the store is not using the default model type. So if you customize the model type, it won't work smoothly with IdentityStoreManager.
Since you only customize the IUser model, I simplified the code to inherit custom user from default identity user and reuse other models from identity EF models.
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.EntityFramework;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Linq;
using System.Web;
namespace WebApplication11.Models
{
public class PulseUser : User
{
public PulseUser() { }
public PulseUser(string userName) : base(userName)
{
}
[StringLength(100)]
public string Email { get; set; }
[Column(TypeName = "Date")]
public DateTime? BirthDate { get; set; }
[StringLength(1)]
public string Gender { get; set; }
}
public class PulseUserContext : IdentityStoreContext
{
public PulseUserContext(DbContext db) : base(db)
{
this.Users = new UserStore<PulseUser>(this.DbContext);
}
}
public class PulseDbContext : IdentityDbContext<PulseUser, UserClaim, UserSecret, UserLogin, Role, UserRole>
{
}
}
The code above should work with preview version of Identity API.
The IdentityStoreManager API in upcoming release is already aware of this issue and changed all the non-EF dependency code into a base class so that you can customize it by inheriting from it. It should solve all the problems here. Thanks.
PulseUser.Id is defined as a string but doesn't appear to be set to a value. Were you meant to be using a GUID for the Id? If so, initialise it in the constructor.
public PulseUser() : this(String.Empty) { }
public PulseUser(string userName)
{
UserName = userName;
Id = Guid.NewGuid().ToString();
}
You will also want to perform a check that the user name doesn't already exist. Look at overriding DbEntityValidationResult in PulseDbContext. Do a new MVC project in VS2013 to see an example.
Since there are alot of changes on this when going to RTM, i have updated the SPA template that uses a WebApi controller for all the identity signin and such. Its a really cool template , if you havent seen it.
I put all my code here:
https://github.com/s093294/aspnet-identity-rtm/tree/master
(Do note, its only for inspiration. I only made it work and nothing more. Properly have a bug or two also).

Creating related attributes when creating new instance of class MVC 4 - Entity Framework

I am just getting into MVC 4 and Entity Framework 5 and want to know if what I am doing is correct?
I have a UserObject and a JobObject, the jobObject has a reference to a User Object.
public class Job
{
public int id { get; set; }
public virtual MyUser User { get; set; }
public JobType JobType { get; set; }
}
When I want to create an instance of the Job I am passing in the query string a parameter UserID, but the Job only deals with an instance of MyUser.
Is the following the correct way to associate the user to the job?
[HttpPost]
public ActionResult Create(Job job, int userid)
{
if (ModelState.IsValid)
{
MyUser staffmember = db.MyUsers.Find(userid);
if (staffmember == null)
{
return View("StaffMemberNotFound");
}
job.User = staffmember;
db.Jobs.Add(job);
db.SaveChanges();
}
}
Or is there a better way to associate the user to the job?
Your way will work but I prefer to simply work with ids if possible.
What I would suggest is that you add a MyUserId property to your Job class (remember to update the database if you are using codefirst):
public class Job
{
public int id { get; set; }
[ForeignKey("User")]
public int MyUserId { get; set: }
public virtual MyUser User { get; set; }
public JobType JobType { get; set; }
}
Then simply populate the MyUserId. You can also change your check to simply check if the id exists as apposed to finding an object and letting EF map that to a class before returning it to you
[HttpPost]
public ActionResult Create(Job job, int userid)
{
if (ModelState.IsValid)
{
if (!db.MyUsers.Any(u => u.Id == userid)
{
return View("StaffMemberNotFound");
}
job.MyUserId = userid;
db.Jobs.Add(job);
db.SaveChanges();
}
}
EF will do the rest of the mapping for you when you next retrieve the record from the database.
Your approach works fine, the only small optmization you could make is not taking the "retrieval hit" of MyUser staffmember = db.MyUsers.Find(userid); since you already have the userid.
I am using ASP.NET MVC 4 and Entity Framework 5.0, and here is my code (different model objects, but same intent as what you are doing).
Note: I let EF generate my model classes by right-clicking on the Models folder and choosing Add->ADO.NET Entity Data Model in VS.NET 2012.
Store.Models.Product
namespace Store.Models
{
using System;
using System.Collections.Generic;
public partial class Product
{
public long Id { get; set; }
public string ProductName { get; set; }
public decimal Price { get; set; }
public int Quantity { get; set; }
public System.DateTime DateAdded { get; set; }
public Nullable<long> CategoryId { get; set; }
public virtual Category Category { get; set; }
}
}
Store.Models.Category
namespace Store.Models
{
using System;
using System.Collections.Generic;
public partial class Category
{
public Category()
{
this.Products = new HashSet<Product>();
}
public long Id { get; set; }
public string CategoryName { get; set; }
public System.DateTime DateAdded { get; set; }
public virtual ICollection<Product> Products { get; set; }
}
}
On my Create.cshtml page, I have the User select the CategoryId from the drop-down list. This Category Id is bound to Product.CategoryId. All I do in my method is this:
ProductController
public class ProductController : Controller
{
...
[HttpPost]
public ActionResult Create(Product product)
{
product.DateAdded = DateTime.Now;
if (dbContext != null)
{
dbContext.Products.Add(product);
dbContext.SaveChanges();
}
return RedirectToAction("Index");
}
...
}

How can I enter in date and username automatically when updating storage?

I have the following class that's used by my MVC3 application. I would like
to simplify the updating of the class so that when a new class object is
created then the Created and CreatedBy fields get set automatically.
I'd also like to make it so that the Modified and ModifiedBy fields get
updated automatically.
Is there a way that I could do this?
The class is used in MVCnamespace Storage.Models
{
public class Topic : TableServiceEntity
{
[DisplayName("Partition Key")]
public override string PartitionKey { get; set; }
[DisplayName("Row Key")]
public override string RowKey { get; set; }
[DisplayName("Description")]
public string Description { get; set; }
public DateTime Created { get; set; }
public DateTime Modified { get; set; }
public String CreatedBy { get; set; }
public string ModifiedBy { get; set; }
}
}
Set the defaults in the constructor for the class
public class Topic
{
public Topic()
{
this.Created = DateTime.Now;
this.CreatedBy = UserName;
}
[DisplayName("Partition Key")]
public override string PartitionKey { get; set; }
[DisplayName("Row Key")]
public override string RowKey { get; set; }
[DisplayName("Description")]
public string Description { get; set; }
public DateTime Created { get; set; }
public DateTime Modified { get; set; }
public String CreatedBy { get; set; }
public string ModifiedBy { get; set; }
}
jonathan,
Jason's answer above with the logic contained within the constructors is a perfectly valid and clean way of doing this and I wouldn't argue with that (and have done it myself for more 'static' properties). However, given that there could be a timelapse between the creation of the object and the actual save, then you may also want to consider putting this logic into your controller (or service layer).
this would look roughly like this:
public ActionResult Create(MyCreateViewModel viewModel)
{
if (ModelState.IsValid)
{
viewModel.Entity.Created = DateTime.UtcNow;
_myService.Insert(viewModel.Entity);
_myService.SaveChanges();
return this.RedirectToAction(x => x.Index());
} else {
PopulateViewModel(viewModel);
return View(viewModel);
}
}
likewise, you may have a LastEdit datetime that you want to track. use the Edit action similarly:
public ActionResult Edit(MyEditViewModel viewModel)
{
if (ModelState.IsValid)
{
viewModel.Entity.LastEditDate= DateTime.UtcNow;
_myService.AttachAndUpdate(viewModel.Entity);
_myService.SaveChanges();
return this.RedirectToAction(x => x.Index());
} else {
PopulateViewModel(viewModel);
return View(viewModel);
}
}
just another approach to ensure that datetime related properties are truly reflected.
In this solution i think you may have to make big change in your Repository/Service layer
define an Interface like :
public interface IHistoryLog
{
DateTime Created { get; set; }
DateTime Modified { get; set; }
string CreatedBy { get; set; }
string ModifiedBy { get; set; }
}
then:
public class Topic:IHistoryLog
{
// Implement interface..
}
then create a generic service class:
public abstract class CRUDService<TModel>
{
protected CRUDService(DataContext dataContext)
{
// data context to do generic CRUD stuff
}
public virtual Save(TModel model)
{
if(model is IHistoryLog)
{
// assign Createdby and Created
}
}
public virtual Update(TModel model)
{
if(model is IHistoryLog)
{
// assign ModifiedBy and Modified
}
}
}

Resources