fetch data from the given id in the controller asp.net mvc - c#

I need to fetch a string from the database which is saved to it when adding a business in my case. I was able to save it to the db via below code in business controller
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ID,Title,Address,Category,Description,Latitude,Longitute,Owner")] Business business)
{
business.Owner = System.Web.HttpContext.Current.User.Identity.Name;//I'm saving the current user as the owner
if (ModelState.IsValid)
{
db.Businesses.Add(business);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(business);
}
Now all I need is to check whether the current user user is the owner of the business which is saved in the model when adding a business as seen in the above code. the model class is below
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace WebPortal.Models
{
public class Business
{
public int ID { get; set; }
public string Title { get; set; }
public string Address { get; set; }
public string Category { get; set; }
public string Description { get; set; }
public double Latitude { get; set; }
public double Longitude { get; set; }
public string Owner { get; set; }//in order to detect the original creator of the businness
}
}
The saving part works fine and here's is the code which i tried to fetch it in the business controller
// GET: Businesses/Edit/5
[Authorize]
public ActionResult Edit([Bind(Include = "ID,Title,Address,Category,Description,Latitude,Longitute,Owner")] int? id, string ownerr, Business business)
{
Business bs = new Business();
//Authorizing Edit permission only for the owner of the business and the admin
if (!((System.Web.HttpContext.Current.User.Identity.Name == bs.Owner
|| User.Identity.Name == "admin#gmail.com" )))
{
return View(db.Businesses.ToList());
}
It's kinda wronge. i just need to know how the fetch the relavent owner of the business by passing the ID maybe...
Edited
Id could be get via below html and i was trying to pass the owner as well but it returns a null in the controller
{
#Html.ActionLink("| Edit | ", "Edit", new { id = item.ID, owner = item.Owner })
#Html.ActionLink("Delete", "Delete", new { id = item.ID })
}

I usually make Identity Id the Id of the models and I use the ApplicationUserManager to query the database for the currently Signed In user
private ApplicationUserManager _userManager;
public ApplicationUserManager UserManager
{
get
{
return _userManager ?? HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
}
private set
{
_userManager = value;
}
}
var user = UserManager.FindById(User.Identity.GetUserId());
var userId = Guid.Parse(user.Id);
var _context = new MessageContext();
var myContacts = _context.Contacts.Where(c => c.CustomerId == userId).ToList();
ViewBag.Contacts = myContacts;

Related

Bind new modal field in asp.net core modal

My code was working file until i added a new field in modal which has only get method
public bool hasShiftingRequest {
//this field is not in database
//it is being calculated everytime you access it
get
{
return _context.AssetShifting.Where(a => a.assetId == this.Id & a.status.Equals("REQUESTED")).Any();
}
}
But it is causing error during my edit method which is binding fronted data with modal
(Basically problem during Binding)
public async Task<IActionResult> Edit(int id, [Bind("Id,make_model,lot,username,email")] AssetDataPc assetDataPc)
and I am getting this error
Please Help !
EDIT
My assetPC modal
public class AssetDataPc
{
public readonly AssetManagementContext _context;
public AssetDataPc(AssetManagementContext context)
{
_context = context;
}
public int ram { get; set; }
[Display(Name = "Remarks")]
public string remarks { get; set; }
[Display(Name = "QR Code Status")]
public string qr_code_status { get; set; }
[DataType(DataType.Date)]
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:dd/MM/yyyy}")]
[Display(Name = "Last updated")]
public DateTime updated_at { get; set; } = DateTime.Now;
[EmailAddress]
[Display(Name = "Email")]
public string email { get; set; }
[Display(Name = "Screen Size")]
public string screen_size { get; set; }
[Display(Name = "Color")]
public string rowColor { get; set; } = "";
public bool hasShiftingRequest {
//this field is not in database
//it is being calculated everytime you access it
get
{
return _context.AssetShifting.Where(a => a.assetId == this.Id & a.status.Equals("REQUESTED")).Any();
}
}
}
EDIT 2
my edit (POST( method is some what like this
public async Task<IActionResult> Edit(int id, [Bind("remarks,qr_code_status,email")] AssetDataPc assetDataPc)
{
if (ModelState.IsValid)
{
assetDataPc.updated_at = DateTime.Now;
_context.Update(assetDataPc);
await _context.SaveChangesAsync();
}
EDIT 3
My edit (Get) method:
public async Task<IActionResult> Edit(int? id)
{
var assetDataPc = await _context.AssetDataPcs.FindAsync(id);
if (assetDataPc == null)
{
return NotFound();
}
return View(assetDataPc);
}
hasShiftingRequest is not in your database?
Then use [NotMapped] if you need to use extra column without adding this column in database so that entity framework core will not check this matching column between model class and table in database.
[NotMapped]
public bool? hasShiftingRequest { get; set; }
Remove AssetManagementContext from your AssetDataPc model. Like this.
public class AssetDataPc
{
[NotMapped]
public bool? hasShiftingRequest { get; set; }
}
"Get" Edit method
public async Task<IActionResult> Edit(int? id)
{
var assetDataPc = await _context.AssetDataPcs.FindAsync(id);
if (assetDataPc == null)
{
return NotFound();
}
else
assetDataPc.hasShiftingRequest = _context.AssetShifting.Where(a => a.assetId == assetDataPc.Id & a.status.Equals("REQUESTED")).Any();
return View(assetDataPc);
}
Solution
--dont use DbContext in modal classes
--use [NotMapped] to avoid creating database field
As the exception states AssetDataPc should have a parameterless constructor in order to be binded. When you added this constructor
public AssetDataPc(AssetManagementContext context)
{
_context = context;
}
it started failing.
Consider moving hasShiftingRequest logic outside the class and just map result to plain property.
As the error message said, Model bound complex types must not be abstract or value types and must have a parameterless constructor. So, you could try to add the default AssetDataPc constructor for the AssetDataPc class.
public class AssetDataPc
{
public readonly AssetManagementContext _context;
public AssetDataPc(){} //add default constructor
public AssetDataPc(AssetManagementContext context)
{
_context = context;
}
...
public bool hasShiftingRequest {
//this field is not in database
//it is being calculated everytime you access it
get
{
return _context.AssetShifting.Where(a => a.assetId == this.Id & a.status.Equals("REQUESTED")).Any();
}
}
}

How to retrieve an object property inside a view

I have an index method in a controller which looks like this :
public ActionResult Index()
{
var object = _ObjectService.GetAll();
return View(object);
}
Which give me a list of object with those properties :
public class Object : EntityWithNameAndId
{
public virtual Site Site { get; set; }
public virtual List<User> Users { get; set; }
public virtual List<Planning> Plannings { get; set; }
public virtual Guid IdPilote { get; set; }
}
Now in my Index() view, i want to get the User who's related to the IdPilote id and display its name.
I tried something like this, thanks to this topic ASP.Net MVC: Calling a method from a view :
#model List<MyClass.Models.Promotion>
#foreach (var item in Model)
{
<td>#item.Site.Name</td>
#{
var id = item.IdPilote;
//Here Interface and Service are folders
var user = MyDAL.Interface.Service.IUserService.Get(id);
}
<td>
//This is where i try to display my User name,
//that i get dynamically using the idPilote for each User in list
</td>
}
But Get(id) is not recognize as a valid method..
public interface IUserService : IDisposable
{
User Get(Guid id);
}
public class UserService : IUserService
{
private MyContext context;
public UserService(MyContext context)
{
this.context = context;
}
public User Get(Guid id)
{
return context.User.Where(w => w.Id == id).SingleOrDefault();
}
}
So what's the best way to get my User object inside my view, since i only get an Id ?
Should i create a new list, using the first one, in my Index method (where i can call IUserInterface.Get()) or is there a better way to do it ?
Make it worked by creating a new list and a specific ViewModel, as suggested :
public class IndexObjectViewModel : EntityWithNameAndId
{
public virtual Site Site { get; set; }
public virtual List<User> Users { get; set; }
public virtual List<Planning> Plannings { get; set; }
//To store User instead of its Id
public virtual User Pilote { get; set; }
}
Now Index() looks like this :
public ActionResult Index()
{
var objects = _IObjectService.GetAll();
ViewBag.NotPromoExist = false;
var indexObj = new List<IndexObjectViewModel>();
foreach (var p in objects)
{
var indexModel = new IndexObjectViewModel();
indexModel.Id = p.Id;
indexModel.Name = p.Name;
indexModel.Site = p.Site;
indexModel.Users = p.Users;
indexModel.Plannings = p.Plannings;
indexModel.Pilote = _IUserService.Get(p.IdPilote);
indexObj.Add(indexModel);
}
return View(indexObj);
}
Everything is done in the controller now. Not sure if it's the best way to do it though..

How to map users identity and Auditable properties in view model

This is my view model.
public class ProductViewModel
{
public Guid Id { get; set; }
public string Code { get; set; }
public string Name { get; set; }
public bool IsAvailable { get; set; }
}
When form is posted from client the form is submitted to this Controller
public async Task<IHttpActionResult> AddProduct(ProductViewModel productViewModel)
{
await ServiceInstances.PostAsync("product/add", productViewModel);
return Ok();
}
Then this controller submit the form to the API controller
Which is on my separate Project.
[HttpPost]
[Route("add")]
public IHttpActionResult AddProduct(ProductViewModel model)
{
_productService.AddProduct(model.UserServiceDetails());
return Ok();
}
Extension UserServiceDetails Where i get the Login User Info
public static UserServiceDetailModel<T> UserServiceDetails<T>(this T model)
{
var serviceRequestModel = new ServiceRequestModel<T>()
{
Model = model,
LoginInfo = HttpContext.Current.User.Identity.GetUserLoginInfo();
};
}
AddProductService:
public void AddProduct(UserServiceDetailModel<ProductViewModel> serviceRequestModel)
{
var repo = _genericUnitOfWork.GetRepository<Product, Guid>();
var mapped = _mapper.Map<ProductViewModel, Product>(serviceRequestModel.Model);
mapped.Id = Guid.NewGuid();
mapped.CreatedDate = GeneralService.CurrentDate();
mapped.CreatedById = serviceRequestModel.LoginInfo.UserId;
repo.Add(mapped);
_genericUnitOfWork.SaveChanges();
}
Now my question is Is there any way to assign the value to this field CreatedDate and CreatedById before posting it to service?
Reduce these logic to mapper:
mapped.CreatedDate = GeneralService.CurrentDate();
mapped.CreatedById = serviceRequestModel.LoginInfo.UserId;
Or is there any way that those field gets mapped to Product when
var mapped = _mapper.Map<ProductViewModel, Product>(serviceRequestModel.Model);
Sometime i may have the List<T> on view-model and there i have to add this field using the loop.
So this same mapping may get repeated over and over on Add Method Or Update.
In some entity i have to assign the ModifiedDate and ModifiedById also.
My Mapper Configuration:
public class ProductMapper : Profile
{
public ProductMapper()
{
CreateMap<ProductViewModel, Product>();
}
}
I cannot add the Enitity as IAuditableEntity and Overrride in ApplicationDbContext because my DbContext is in separate Project and i donot have access to Identity there.

ASP.Net Identity .FindIdAsync not finding user?

I’m still working on trying to get a sample app with Identity 2 working. In the following post I got help adding role information to a ViewModel to display my users.
Need understanding on how to get/display User Role
Now I’m trying to address an issue I have when I click on the Edit button of the user. My controller keeps coming up NULL for the user when I try finding it with the .FindIdAsync method. However, in debug mode I can see the correct ID being passed into the Edit ActionResult.
Would the fact that I’m using a ViewModel in my Index View have anything to do with it? I would have thought that since the ID is being passed correctly that the ViewModel would be out of the picture at that point.
I’ve searched over the web but can’t find anything to help me figure out the problem.
This is the ActionResult and in debug I can see the id being populated with the correct value. So, I have no idea why it’s not finding the record. There are no error messages, it's just returning a NULL for the user object which is displaying the "User Not Found" error on every user I have in my table.
I'm hoping someone can help point me at something I can look at to help figure this one out.
public async Task<ActionResult> Edit(string id)
{
AppUser user = await UserManager.FindByIdAsync(id);
if (user != null)
{
return View(user);
}
else
{
return View("Error", new string[] { "User Not Found" });
}
}
public class AppUser : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
This is the ViewModel I’m using on the Index View which I wouldn’t think would have anything to do with this issue but showing it just in case.
public class UserEditVM : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string UserRole { get; set; }
public IEnumerable<AppRole> AllRoles { get; set; }
}
And here is my AppUserManager
public class AppUserManager : UserManager<AppUser>
{
public AppUserManager(IUserStore<AppUser> store)
: base(store)
{
}
public static AppUserManager Create(
IdentityFactoryOptions<AppUserManager> options,
IOwinContext context)
{
AppIdentityDbContext db = context.Get<AppIdentityDbContext>();
AppUserManager manager = new AppUserManager(new UserStore<AppUser>(db));
manager.PasswordValidator = new CustomPasswordValidator
{
RequiredLength = 6,
RequireNonLetterOrDigit = false,
RequireDigit = false,
RequireLowercase = true,
RequireUppercase = true
};
manager.UserValidator = new CustomUserValidator(manager)
{
AllowOnlyAlphanumericUserNames = true,
RequireUniqueEmail = true
};
return manager;
}
}
UPDATE: here is my updated ViewModel. Removed inheritance and added the properties I needed from IdentityUser.
public class UserEditVM
{
public string Id { get; set; }
public string UserName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string UserRole { get; set; }
public IEnumerable<AppRole> AllRoles { get; set; }
}
I guess, if you just use the existing Identity Model and implement a class like below which inherits Interfaces like IUserStore<User>, IUserLoginStore<User> You might be able to handle any Async methods yourselves.
Example: refer code below, btw this code uses dapper, so you might use your own ORM:
public class UserStore : IUserStore<User>, IUserLoginStore<User>, IUserPasswordStore<User>, IUserRoleStore<User>
{
private readonly string connectionString;
public UserStore()
{
this.connectionString = ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;
}
/// <summary>
/// Returns User tables information, based on parameter type userId/Username will be equated in where condition
/// </summary>
/// <param name="userId">userId or Username can be passed</param>
/// <returns></returns>
public virtual Task<User> FindByIdAsync(string userId)
{
if (string.IsNullOrWhiteSpace(userId.ToString()))
throw new ArgumentNullException("userId", string.Format("'{0}' is not a valid format.", new { userId }));
return Task.Factory.StartNew(() =>
{
var parameters = new DynamicParameters();
parameters.Add("#userId", userId);
using (SqlConnection connection = new SqlConnection(connectionString))
return connection.Query<User>("spUsers_GetUser", parameters, commandType: CommandType.StoredProcedure).SingleOrDefault();
});
}
}

How to test if my linq query went through

This is my code from my controller:
MGEntities db = new MGEntities();
[HttpPost]
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
// Attempt to register the user
MembershipCreateStatus createStatus = MembershipService.CreateUser(model.UserName, model.Password, model.Email);
if (createStatus == MembershipCreateStatus.Success)
{
FormsService.SignIn(model.UserName, false /* createPersistentCookie */);
MembershipUser myObject = Membership.GetUser();
Guid UserID = (Guid)myObject.ProviderUserKey;
MyProfile profile = new MyProfile();
profile.Address = model.Address;
profile.City = model.City;
profile.Zip = model.Zip;
profile.State = model.State;
profile.UserId = UserID;
Debug.Write(profile.State);
db.aspnet_Profiles.Add(profile);
return RedirectToAction("Index", "Home");
}
else
{
ModelState.AddModelError("", AccountValidation.ErrorCodeToString(createStatus));
}
}
This is my MyProfile Class:
namespace MatchGaming.Models
{
[Bind(Exclude = "ProfileId")]
public class MyProfile
{
[Key]
[ScaffoldColumn(false)]
public int ProfileId { get; set; }
public Guid UserId { get; set; }
[DisplayName("Address")]
public string Address { get; set; }
[DisplayName("City")]
public string City { get; set; }
[DisplayName("Zip")]
public string Zip { get; set; }
[DisplayName("State")]
public string State { get; set; }
}
}
After the linq query is executed, i check my database and nothing is added. I am using POCO for my entities. Here is my class:
namespace MatchGaming.Models
{
public class MGEntities : DbContext
{
public DbSet<MyProfile> aspnet_Profiles { get; set; }
}
}
I basically just dont understand why its not adding to the database, if theres a way I can check if the query went through correctly or not or if anyone can see the problem. Thank you!
Try
db.aspnet_Profiles.Add(profile);
db.SaveChanges();
You're misusing EF.
EF contexts are not thread safe and cannot be reused across requests.
You need to create a separate context (MGEntities) for each request, by creating it in the controller in a using statement.
You also need to call SaveChanges().

Categories