I have a method to retrieve session variables, in this case Organizations. For some reason, when I call the get session method the get Organizations and pass the data to a SelectList method to handle some naming logic, the session variable is getting updated. I don't wanted the session values updated and don't understanding what is happening. Below are all the methods. What am I missing?
Controller Method:
public ActionResult Create()
{
SignUpEventFormModel model = new SignUpEventFormModel();
SelectListHelpers listHelper = new SelectListHelpers();
model.OrganizationList = listHelper.GetOrgSelectList(sessionRepository.GetUserSession().Organizations, null);
return View(model);
}
Get User Session Method:
public UserSession GetUserSession()
{
UserSession us = (UserSession)HttpContext.Current.Session["UserSession"];
if (us == null)
{
string email = HttpContext.Current.User.Identity.Name;
SessionSetupRepository sessionsetupRepository = new SessionSetupRepository(new UserRepository(null, null), new SignUpRepository(), new ActivityRepository(), new OrganizationRepository());
us = sessionsetupRepository.SetupUserSession(email);
}
return us;
}
Get Org Select List Method:
public SelectList GetOrgSelectList(IEnumerable<Organization> Orgs, int? SelectedOrgID)
{
List<Organization> OrgList = Orgs.ToList();
OrgList.Where(o => !o.IsAdmin).ToList().ForEach(o => o.Name = o.Name + " (Permission Request Required)");
if (SelectedOrgID.HasValue)
return new SelectList(OrgList, "OrganizationID", "Name", (int)SelectedOrgID);
else
return new SelectList(OrgList, "OrganizationID", "Name");
}
Created a IList parameter and converted the organizations to a list.
Related
I wanted to return a list to my partial view from relational matching data of products. I have attached picture of edmx file where you will get idea about their relationship status! Problem is i just dont know how can i write this query or i need any iteration process to do it. Main goal is: I want to get all Products that the current user has bookmarked. Any question welcome. Thanks in advance
[ChildActionOnly]
[Authorize]
public PartialViewResult _UserBookmark(string id)
{
using (mydb db = new mydb())
{
int userId = db.Users.Where(x => x.Email == id).FirstOrDefault().UserId;//here i am getting user primary key id
var ProductIds = db.Bookmarks.Where(x => x.UserId == userId).ToList();//here i am getting all Product primary keys under that user
var ListOfProducts = db.Products.Where(x=>x.ProductId == "i dont know how to do it") // here i wanted to return matched all products
return PartialView("_UserBookmark",ListOfProducts);
}
}
You can use a .Contains statement to return the Products where the ProductId is in your collection of ProductIds.
Change the method to
[ChildActionOnly]
[Authorize]
public PartialViewResult _UserBookmark(string id)
{
using (mydb db = new mydb())
{
int userId = db.Users.Where(x => x.Email == id).FirstOrDefault().UserId;
// Get a collection of the ProductId's
IEnumerable<int> ProductIds = db.Bookmarks
.Where(x => x.UserId == userId).Select(x => x.ProductId);
IEnumerable<Product> ListOfProducts = db.Products
.Where(x => ProductIds.Contains(x.ProductId))
return PartialView("_UserBookmark", ListOfProducts);
}
}
Note, if the results are for the current user, then consider just getting the current user in the method rather that passing their Email to the method. Note also that .FirstOrDefault().UserId would throw an exception is you passed an incorrect value to the method which resulted in User being null.
I'm just getting started with MVC5 (from WebForms), and dropdownlist bindings are giving me some fits.
I'd like to get this working using a GET request back to the page, with a selected value parameter. I'm hopeful that I can specify the route arguments in the form itself, so I'd like to reference the DDL's SelectedValue.
<p>
#using (Html.BeginForm("Index", "Profile", FormMethod.Get, new { id = WHATDOIPUTHERE} )) {
#Html.AntiForgeryToken()
#Html.DropDownList("ApplicationID", new SelectList(ViewBag.ApplicationList, "ApplicationID", "ApplicationName", ViewBag.SelectedApplicationId), new {onchange = "this.form.submit();"})
}
</p>
I can make it work with a POST form, but that requires a second controller method so I end up with
public ActionResult Index(long? id) {
ConfigManager config = new ConfigManager();
//handle application. default to the first application returned if none is supplied.
ViewBag.ApplicationList = config.GetApplications().ToList();
if (id != null) {
ViewBag.SelectedApplicationId = (long)id;
}
else {
ViewBag.SelectedApplicationId = ViewBag.ApplicationList[0].ApplicationID; //just a safe default, if no param provided.
}
//handle profile list.
List<ProfileViewModel> ps = new List<ProfileViewModel>();
ps = (from p in config.GetProfilesByApp((long)ViewBag.SelectedApplicationId) select new ProfileViewModel(p)).ToList();
return View(ps);
}
//POST: Profile
//read the form post result, and recall Index, passing in the ID.
[HttpPost]
public ActionResult index(FormCollection collection) {
return RedirectToAction("Index", "Profile", new {id = collection["ApplicationId"]});
}
It would be really nice to get rid of the POST method, since this View only ever lists child entities.
What do you think?
You can update your GET action method parameter name to be same as your dropdown name.
I also made some small changes to avoid possible null reference exceptions.
public ActionResult Index(long? ApplicationID) {
var config = new ConfigManager();
var applicationList = config.GetApplications().ToList();
ViewBag.ApplicationList = applicationList ;
if (ApplicationID!= null) {
ViewBag.SelectedApplicationId = ApplicationID.Value;
}
else
{
if(applicationList.Any())
{
ViewBag.SelectedApplicationId = applicationList[0].ApplicationID;
}
}
var ps = new List<ProfileViewModel>();
ps = (from p in config.GetProfilesByApp((long)ViewBag.SelectedApplicationId)
select new ProfileViewModel(p)).ToList();
return View(ps);
}
I have a Controller where on the Create action I need the user ID.
Here's the controller.
public ActionResult Create(MyCreateViewModel model)
{
if (ModelState.IsValid)
{
var myobject = new MyObject
{
Attrib1 = DateTime.Now.Date,
Attrib2 = model.Etichetta,
UserId = // I need the user ID...
};
// Save the object on database...
return RedirectToAction("Index");
}
return View(model);
}
I'm using the UserProfile table provided with the SimpleMembership of MVC 4.
Which is the best practice in MVC 4 to manage the userID across the application?
Do I have to include a User attribute inside every Entity class?
Should I use a Session[] variable or what?
You can use this line to get the userId from the UserProfiles table.
var userId = WebSecurity.GetUserId(HttpContext.Current.User.Identity.Name);
You can also use this function to get the users complete profile, including any custom columns you may be populating.
public static UserProfile GetUserProfile()
{
using (var db = new UsersContext())
{
var userId = WebSecurity.GetUserId
(HttpContext.Current.User.Identity.Name);
var user = db.UserProfiles
.FirstOrDefault(u => u.UserId == userId);
if (user == null)
{
//couldn't find the profile for some reason
return null;
}
return user;
}
}
Here is my problem step by step,
1- I do ajax get request from my external javascript file as following,
$.ajax({
type: "GET",
dataType: 'json',
url: '/Company/GetCompanies',
error: function (xhr, status, error) {
alert('error');
return false;
},
success: function (response) {
alert('success');
return false;
}
});
2 - This is the action method that receives the request
public ActionResult GetCompanies()
{
var model = new CompanyIndex();
model.FillCompanies();
return Json(model ,JsonRequestBehavior.AllowGet);
}
3 - CompanyIndex is a ViewModel that is created in my action method above.
public class CompanyIndex
{
public IList<Company> Companies { get; set; }
public void FillCompanies()
{
/* Part that is not working */
UnitOfWork unitOfWork = new UnitOfWork();
Companies = unitOfWork.CompanyRepository
.Get(orderBy: q => q.OrderBy(u => u.CompanyName)).ToList();
unitOfWork.Dispose();
/****************************/
/* This works fine */
var companyList = unitOfWork.CompanyRepository
.Get(orderBy: q => q.OrderBy(u => u.CompanyName)).ToList();
Companies = companyList.Select(x => new { name = x.CompanyName }).ToList()
.Select(x => new Company
{
CompanyName = x.name
}).ToArray<Company>();
/********************/
}
}
As you can see I fetch company entities from the database using my repository and Get method that I also share below. The problem is when I fetch them from database, the type of the model that is retrieved is System.Data.Entity.DynamicProxies.Company_someRandomStringHere. In this case Ajax get request does not succeed and alerts error message.
However, if I first fetch from db and create Company objects in ViewModel and assign them to my List, ajax works fine, and ajax get request returns success. And type of Company entities when I create objects at ViewModel is CompanyManagement.Models.Company as it should be.
Just in case you need it this is the Get method I am using to fetch data from db.
public virtual IEnumerable<TEntity> Get(
Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
string includeProperties = "")
{
IQueryable<TEntity> query = dbSet;
if (filter != null)
query = query.Where(filter);
foreach (var includeProperty in includeProperties.Split
(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
query = query.Include(includeProperty);
if (orderBy != null)
return orderBy(query).ToList();
else
return query.ToList();
}
I don't want to manually create new Company objects. Any ideas are really appreciated. Thanks in advance.
Found the problem. It seems the respond of Ajax request needs to be serializable. To do that, I canceled dynamic proxies with,
context.ContextOptions.ProxyCreationEnabled = false;
As a result my Get function now returns CompanyManagement.Models.Company entities instead of System.Data.Entity.DynamicProxies.Company.
Edit:
Use viewmodels to populate your views, do not return entities keeping your business logic to client side. This is bad practice and dangerous in some cases.
I had a similar problem once and i have to do it manually like this
/* Part that is not working */
UnitOfWork unitOfWork = new UnitOfWork();
Companies = unitOfWork.CompanyRepository
.Get(orderBy: q => q.OrderBy(u => u.CompanyName))
.Select(x => new Company()
{
fooAttribute = x.fooAtribute
}).ToList();
I've got an Edit action like this:
[HttpPost]
public ActionResult Edit(UserModel user1)
{
if (ModelState.IsValid)
{
UserManager um = new UserManager();
String mail = User.Identity.Name;
long id = um.getUserIDByemail(mail);
user user = db.users.Single(u => u.user_id == id);
user.name = user1.name;
user.cellno = user1.cellno;
db.users.Attach(user);
db.ObjectStateManager.ChangeObjectState(user, EntityState.Modified);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(user1);
}
I've got user object exactly what I want to update. Two properties (name, cellno) of user comes from a view. When I run it I get an error:
The object cannot be attached because it is already in the object context. An object can only be reattached when it is in an unchanged state.
I think you can just remove the Attach and it should work.