I am showing search results same as searching groups on facebook
enter image description here
I have a relationship Table named CommunityUser in Database having attributes CommunityID and UserID.
Using Partial View I want to show if User not already joined that Community/Group that it will show Join Button else if user already joined that community it will show Leave button.
I have written IsMember() function in my controller that takes two parameters, CommunityID and UserID. This will return true if that Community ID exist against that user ID.
public bool IsMember(string UserID, int CommunityID) {
var Membership = db.Users.Include(x => x.CommunityUsers).Where(s => s.Id.Equals(UserID)).Count();
if(Membership>0)
return true;
else
return false;
}
Now what I actually need is, I want to call this function in an IF condition on my view class. It is not allowing me to call this function on my view Class.
#if (){
<button>#Html.ActionLink("Leave", "LeaveCommunity", new { id = ViewBag.ComID })</button>
}
else
{
<button>#Html.ActionLink("Join", "joinCommunity", new { id = ViewBag.ComID })</button>
}
In your controller you should have a method which will return this view. So in this method you call this function
public ActionResult Index(string UserID, int CommunityID)
{
var hasMembership = IsMember(serID, CommunityID);
return View(hasMembership);
}
In the View it self then you just grab this variable hasMembership you just passed from #model.
#if (Model){
<button>#Html.ActionLink("Leave", "LeaveCommunity", new { id = ViewBag.ComID })</button>
}
else
{
<button>#Html.ActionLink("Join", "joinCommunity", new { id = ViewBag.ComID })</button>
}
Note: it might be wise to create some DTO class for passing data to a view, because you might need to pass multiple value to a view at some point. Plus the whole condition would be more readable
public SomeDTO {
public bool IsMember {get;set}
public List<Community> Communities {get;set;}
}
public ActionResult Index(string UserID, int CommunityID)
{
var hasMembership = IsMember(serID, CommunityID);
var listOfCommunities = _repo.GetComunities();
var dto = new SomeDTO
{
IsMember = hasMembership,
Communities = listOfCommunities
}
return View(dto);
}
#if (Model.IsMember){
// do or do not something
}
Related
This question already has answers here:
The ViewData item that has the key 'XXX' is of type 'System.Int32' but must be of type 'IEnumerable<SelectListItem>'
(6 answers)
Closed 6 years ago.
In my MVC project I pass list of currencies to the view within the drop down list. However, once I try to post the view I get the following exception:
The ViewData item that has the key 'FromCurrencyId' is of type
'System.Int32' but must be of type 'IEnumerable'.
Currency Controller
namespace Project.Controllers
{
public class CurrencyController : Controller
{
[HttpGet]
// GET: Currency
public ActionResult Index()
{
CurrenciesClient Cur = new CurrenciesClient();
var listCurrency = Cur.findAll().ToList();
Currencies model = new Currencies();
model.FromCurrencies = new SelectList(listCurrency, "Id", "CurrencyName");
model.ToCurrencies = new SelectList(listCurrency, "Id", "CurrencyName");
return View(model);
}
[HttpPost]
public ActionResult Index(Currencies cur)
{
if (ModelState.IsValid)
{
if (cur.FromCurrencyId == cur.ToCurrencyId)
{
//do something if same currecnies and return.
ModelState.AddModelError("CurrencyCountry", "Can't make the conversion for the same value");
}
else
{
some code .....
}
}
return View(cur);
}
}
}
Currencies VM
namespace Project.ViewModels
{
public class Currencies
{
public int Id { get; set; }
[Required]
public int FromCurrencyId { get; set; }
public SelectList FromCurrencies { get; set; }
[Required]
public int ToCurrencyId { get; set; }
public SelectList ToCurrencies { get; set; }
public string CurrencyName { get; set; }
public string CurrencyCountry { get; set; }
[Required]
public decimal ConversionRate { get; set; }
public decimal Value { get; set; }
public SelectList AvailableCurrencies { get; set; }
}
}
CurrencyClient web service VM
namespace Project.ViewModels
{
public class CurrenciesClient
{
private string base_Url = "http://localhost:51646/api/";
public IEnumerable<Currencies> findAll()
{
try
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(base_Url);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.GetAsync("currencies").Result;
if (response.IsSuccessStatusCode)
{
var resposeData = response.Content.ReadAsStringAsync().Result;
var Currency = JsonConvert.DeserializeObject<List<Currencies>>(resposeData);
return Currency;
}
return null;
}
catch
{
return null;
}
}
}
}
Index View
model Project.ViewModels.Currencies
#{
ViewBag.Title = "Index";
}
#using (Html.BeginForm("Index", "Currency", FormMethod.Post))
{
#Html.TextBoxFor(m => m.ConversionRate, new { #size = "5" })
#Html.DropDownListFor(m => m.FromCurrencyId, Model.FromCurrencies as IEnumerable<SelectListItem>)
#Html.DropDownListFor(m => m.ToCurrencyId, Model.ToCurrencies as IEnumerable<SelectListItem>)
<button type="submit" class="btn btn-primary">Convert</button>
}
This problem is becuase you are passing null value from your dropdown.Means you are not selecting any value. Check that if you will pass some value from dropdown it will work fine.To solve this problem you need to add the same
code
Currencies model = new Currencies();
model.FromCurrencies = new SelectList(listCurrency, "Id", "CurrencyName");
model.ToCurrencies = new SelectList(listCurrency, "Id", "CurrencyName");
in your controller index post method.Because if selectListitem would be null the following code will be executed
IEnumerable<SelectListItem> selectList = o as IEnumerable<SelectListItem>;
if (selectList == null)
{
throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture,
MvcResources.HtmlHelper_WrongSelectDataType,
name, o.GetType().FullName, "IEnumerable<SelectListItem>"));
}
Which will throw exception.
(It would be better if you will use
ViewBag.FromCurrencies = new SelectList(listCurrency, "Id", "CurrencyName");
like this.)
The better description is given here:
The ViewData item that has the key 'XXX' is of type 'System.Int32' but must be of type 'IEnumerable<SelectListItem>'
The whole explanation is also given in this link like how does this code work.
you will have to set the Dropdown data in the post controller as well, otherwise it will not be able to find the ViewBag values, as a result when after post action it calls the Index view, the ViewBag.FromCurrencies and ViewBag.ToCurrencies will be null which is obviously that we don't want.
For fixing the error, you will have to change you post action to be like:
[HttpPost]
public ActionResult Index(Currencies cur)
{
if (ModelState.IsValid)
{
if (cur.FromCurrencyId == cur.ToCurrencyId)
{
//do something if same currecnies and return.
ModelState.AddModelError("CurrencyCountry", "Can't make the conversion for the same value");
}
else
{
some code .....
}
}
CurrenciesClient Cur = new CurrenciesClient();
var listCurrency = Cur.findAll().ToList();
Currencies model = new Currencies();
model.FromCurrencies = new SelectList(listCurrency, "Id", "CurrencyName");
model.ToCurrencies = new SelectList(listCurrency, "Id", "CurrencyName");
return View(cur);
}
You should not return the view from your POST action or you will run into many issues. Here is the problem with that:
When you submit the form the URL is pointing to your Index. The body of your http post will have a bunch of Currencies items in it. Therefore, MVC, will submit the form to your Index method with Currencies cur parameter.
If all is well you return the same view.
If you refresh the page, your browser will simply reissue the last request and guess what, it will submit the form again. But this is not what you intended by refreshing. You wanted to get the form as it was originally presented not resubmit it.
Therefore instead of returning a view from a POST, you should always, except if AJAX was used, return a redirect.
In this case if all goes well, you may want to send the user to a success page or some other page so you should do this:
return RedirectToAction("YourActionName", "YourControllerName");
This pattern is called the PRG pattern. What this does is this:
user submits a form
If all goes well on the server side, you tell the browser to issue another request and get another page.
The browser gets the other page which may be a success page.
Now the user is on the success page. If they hit refresh they will get the success page again. They will not be submitting the same form over and over.
I'm currently trying to implement a Dropdown List with what I would assume is hardcoded values. Basically what I want is to have a Dropdown List with a choice of three possible values.
I have a total of 4 controllers and views that will be using this dropdown. I've seen a lot of examples for MVC2 and MVC3 where people have hard coded their dropdowns in their views, and I personally don't prefer to go with a quick and "dirty" fix such as that.
I have a model containing the following.
public class Status
{
public int id { get; set; }
public string status { get; set; }
public Status(int statusId, string statusName)
{
id = statusId;
status = statusName;
}
}
The status should be able to have any of the 3 possible values:
Active
Inactive
Processing
I thought of creating the status' using this method I currently have in my status class:
public static List<Status> getAllStatus()
{
List<Status> states = new List<Status>();
states.Add(new Status(1, "Active"));
states.Add(new Status(2, "Inactive"));
states.Add(new Status(3, "Processing"));
return states;
}
I haven't been able to figure out how to use this model inside my Controllers alongside with how to pass it along to my views and was hoping someone in here would known how to do that?
EDIT1:
I guess I forgot to mention that I will be storing the selected value as a string in my database and that I am using a view which doesn't have the model of my status class, but rather the model of object which I will be storing in my database (which might be the case of a vehicle object).
EDIT2:
I have a model called Customer, which has some of the following values:
public int CustomerID { get; set }
public string Email { get; set }
public string Phone { get; set }
public Status Status { get; set; }
In my DB for my Customer model I have a string in which I wan to store the selected Status.
So basically I wan't to change the following to a dropdown with 3 options, Inactive, Active and Processing.
However I don't want to code this in my view as I will be needing it in 8 different views and copy pasting that is not very sleek code.
#Html.DropDownListFor(m => m.status_id, new SelectList(getAllStatus(), "id", "status"))
It doesn't make much sense to save it as a string within your database as it sounds more like something static. So u should consider an Enum. To me more precise look to my previous answer and add those Model properties to a ViewModel.
public class CustomerViewModel () {
public int SelectedStatusId { get; set; }
[DisplayName("Status")]
public IEnumerable<SelectListItem> StatusItems
{
get
{
yield return new SelectListItem { Value = "", Text = "- Select a status -" };
StatusTypeEnum[] values = (StatusTypeEnum[])Enum.GetValues(typeof(StatusTypeEnum));
foreach (StatusTypeEnum item in values)
{
if (item != StatusTypeEnum.Unknown)
{
yield return new SelectListItem { Value = ((int)item).ToString(), Text = item.GetDescription() };
}
}
}
}
}
Pass this into your View through your controller:
public class CustomerCOntroller(){
public ActionResult Index(){
CustomerViewModel viewModel = new CustomerViewModel();
return View(viewModel);
}
}
And you are done. If u are more working with a list which u need to build up add it to your viewModel object.
Greetings,
S..
To start you have a lot of vague questions. Be more specific if you can. If you don't know how MVC works that well I would recomment to follow some tutorials on it.
Model.cs (A ViewModel is preferred). You Should create a ViewModel which you passes to the View. Below is an example how to get a list of items.
public int SelectedStatusId { get; set; }
[DisplayName("Status")]
public IEnumerable<SelectListItem> StatusItems
{
get
{
yield return new SelectListItem { Value = "", Text = "- Select a status -" };
StatusTypeEnum[] values = (StatusTypeEnum[])Enum.GetValues(typeof(StatusTypeEnum));
foreach (StatusTypeEnum item in values)
{
if (item != StatusTypeEnum.Unknown)
{
yield return new SelectListItem { Value = ((int)item).ToString(), Text = item.GetDescription() };
}
}
}
}
StatusTypeEnum.cs
public enum StatusTypeEnum()
{
[Description("Active")] // For correct naming
Active,
Inactive,
Processing
}
View.cshtml
#Html.DropDownListFor(x => Model.SelectedStatusId, Model.StatusItems)
EnumAttribute.cs (To read the Annotation Descriptions. And don't try to understand this. It's just magic. It gets the DataAnnotation of the enum types by reflection.)
public static class EnumAttribute
{
public static string GetDescription<TEnum>(this TEnum value)
{
var fi = value.GetType().GetField(value.ToString());
if (fi != null)
{
var attributes = (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attributes.Length > 0)
{
return attributes[0].Description;
}
}
return value.ToString();
}
}
You could declare States as public propery in your class and use this to access it in your views:
<ComboBox Grid.Column="1" Grid.Row="0" Margin="5"
VerticalAlignment="Center" ItemsSource="{Binding States}"
IsTabStop="False"}"/>
I'm trying to display recently viewed products and so far I have already done that. I have a Product table that has many products stored. I have HomeController which has an Action method of Details() that display product details.
I have wrote AddRecentProduct method which stores Recently Viewed Products (10) in the Session
Now I want to store these recent viewed product list into cookies for atleast 30days on visitors computer, because session expires. Just like Imdb Recently Viewed.
Also If I create another table in my database RecentlyViewed with columns rv_id, userId, productId how will I save recentlyViewedList data in this ? The userId column will hold loggedIn user's id but what if a user is a Guest (not registered) what's the solution then ? Do I need to use GUID then ?
RecentProduct.cs
public class RecentProduct
{
public int ProductId { get; set; }
public string ProdutName { get; set; }
public string ImageUrl { get; set; }
public DateTime LastVisited { get; set; }
}
Controller
public void AddRecentProduct(List<RecentProduct> list, int id, string name, int maxItems)
{
var item = recentProductList.FirstOrDefault(t => t.ProductId == id);
if (item == null)
{
list.Add(new RecentProduct
{
ProductId = id,
ProdutName = name,
LastVisited = DateTime.Now,
});
}
while (list.Count > maxItems)
{
list.RemoveAt(0);
}
}
public ActionResult Details(int? id)
{
if (id == null)
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
Product product = db.Products.Find(id);
if (product == null)
return HttpNotFound();
var list = Session["RecentProductList"] as List<RecentProduct>;
if (list == null)
{
list = new List<RecentProduct>();
Session["RecentProductList"] = list;
}
AddRecentProduct(list, id.Value, product.Name, 10);
ViewData["RecentProductList"] = list;
return View(product);
}
ProductDetails View Page
<div class="col-sm-9">
#{
var recentProductList = ViewData["RecentProductList"] as List<Project.Models.RecentProduct>;
}
#foreach (var recentProduct in recentProductList)
{
<p>#recentProduct.ProdutName (id: #recentProduct.ProductId) </p>
}
</div>
I am getting the desired result with session, Now I want to do this same with cookies.
This is what I'm trying Creating cookie:
List<RecentProduct> yourList = new List<RecentProduct>();
RecentProduct rc = new RecentProduct();
rc.ProdutName = product.Name;
rc.ProductId = product.ProductId;
rc.ImageUrl = product.ImagePath;
rc.LastVisited = DateTime.Now;
yourList.Add(rc);
var yourListString = String.Join(",", yourList);
// Create a cookie
HttpCookie yourListCookie = new HttpCookie("YourList", yourListString);
// The cookie will exist for 7 days
yourListCookie.Expires = DateTime.Now.AddDays(7);
// Write the Cookie to your Response
Response.Cookies.Add(yourListCookie);
and In ProductDetails View Page reading cookies like this:
#if (Request.Cookies["YourList"] != null)
{
// Your cookie exists - grab your value and create your List
List<string> yourList = Request.Cookies["YourList"].Value.Split(',').Select(x => Convert.ToString(x)).ToList();
// Use your list here
<p>#yourList</p>
}
I'm not getting any result. How can I read cookie and values ?
the best solution for you is using Html5 Web Storage. it lets you store up to 5mb in local browser. you can only read and write via javascript.
example:
$('#btnLocalStorage').click(function()
{
var txtName = $("#txtName").val();
//set item
localStorage.setItem("EmpName", txtName);
});
$('#btnLocalStorageRemove').click(function()
{
//remove item
localStorage.removeItem("EmpName");
});
$('#btnLocalStorageClear').click(function()
{
//clear Local Storage
localStorage.clear();
});
$('#btnLocalStorageLength').click(function()
{
var localStoragelength = localStorage.length;
alert("The length of Local storage is " + localStoragelength);
});
By the way it has no expire time and u dont need guid.
If you are using cookies, why do you need RecentlyViewed table then? Storing recent product ids in cookie will work for both logged-in and anonymous user.
I have a web page that is using a number of different partial views and different viewmodels for each partial. One of the partials is for the ability for a user to change their username. Since we are going to allow email addresses as usernames now, I would like to pre-populate the textbox with their current email address from another partial view on the page. How can this be done properly so the value will be populated in the text box and then saved when the submit to the controller happens? Here is a brief code snippet from what I'm looking at:
The view:
#Html.TextBoxFor(model => model.NewUsername, new { id = "uName_change" }) #Html.ValidationMessageFor(model => model.NewUsername)
It's worth noting here that I have tried setting the current email address into ViewData and ViewBag and putting "#value = viewdatahere" into the textbox for properties, but this didn't populate the string, it just left it blank.
I just need to know how this is done. Any help is appreciated.
Edit to add controller POST and GET methods:
[HttpGet]
[ClaimsPrincipalPermission(System.Security.Permissions.SecurityAction.Demand, Resource = Resources.User, Operation = Operations.Edit)]
public ActionResult ChangeUsername(Guid uniqueUserId)
{
User user = UserManager.GetUser(uniqueUserId);
AuthorizationHelper.ConfirmAccess(Resources.User, Operations.Edit, user);
ChangeUsername model = new ChangeUsername(){UserGuid = user.Identifier,NewUsername = user.Username};
return View(model);
}
[HttpPost]
[ClaimsPrincipalPermission(System.Security.Permissions.SecurityAction.Demand, Resource = Resources.User, Operation = Operations.Edit)]
public ActionResult ChangeUsername(ChangeUsername changeUsername)
{
User usr = UserManager.GetUser(changeUsername.UserGuid);
AuthorizationHelper.ConfirmAccess(Resources.User, Operations.Edit, usr);
if (!ModelState.IsValid)
{
return View(changeUsername);
}
//setup request
SupportUser su = (SupportUser)ViewData["SupportUser"];
RequestData rqd = new RequestData(GetApplicationIdentifer(usr), su.clientIP, su.lanID);
UserUsernameChangeRequest request = new AdminUsernameChangeRequest(rqd,usr,changeUsername.NewUsername);
UserUsernameChangeResponse response = UserManager.ChangeUserUsername(request);
if (response.Status == UserProcessorStatus.Success)
{
var message = ("User has been updated successfully");
TempData["message"] = message;
return PartialView("_NewUsername", changeUsername);
}
switch (response.Status)
{
case UserProcessorStatus.DuplicateUsername:
{
ModelState.AddModelError("NewUsername", "Duplicate username");
changeUsername.AlternateUsernames = response.AlternateUsernames;
return PartialView(changeUsername);
}
default:
{
ModelState.AddModelError("NewUsername", String.Format("An unexpected error occured. Error Code:{0}, Message:{1}", response.Status, response.Message));
return PartialView(changeUsername);
}
}
}
There it is.
The last time that I tried to do this was with MVC 3, but I do know that this technique worked then. It's a stupid difference, that's why I pointed that out first.
You were very close with your attempt at it, but you need to set the property as #Value, not #value. I never looked to hard into why the capital made a huge difference. (Like I said, it's a stupid difference.)
var val = "Dummy Value";
#Html.TextBoxFor(model => model.NewUsername, new { id = "uName_change", #Value = val })
Here's how I'd do it.... in the main page set up a viewmodel that contains the other view models like this:
public class VMMain(){
public void VMMain(){
//don't forget null CTOR as MVC requires it...
}
public void VMMain(Guid userguid, string newusername){
UserGuid = userguid;
NewUserName = newusername;
Part1 = new VM1(UserGuid, NewUserName);
Part2 = new VM2();
Part3 = new VM3();
}
public VM1 Part1 {get;set;}
public VM2 Part2 {get;set;}
public VM3 Part3 {get;set;}
Guid UserGuid {get;set;}
string NewUsername {get;set;}
}
In your main view you can bind to anyone of these viewmodels and properties within them. Just make sure you have a property available to bind.
This would change your controller to look like this:
[HttpGet]
[ClaimsPrincipalPermission(System.Security.Permissions.SecurityAction.Demand, Resource = Resources.User, Operation = Operations.Edit)]
public ActionResult ChangeUsername(Guid uniqueUserId)
{
User user = UserManager.GetUser(uniqueUserId);
AuthorizationHelper.ConfirmAccess(Resources.User, Operations.Edit, user);
var model = new VMMain(){UserGuid = user.Identifier,NewUsername = user.Username};
And now you can bind to say Partial ViewModel 1 that has that property like this:
#Html.TextBoxFor(p => model.Part1.NewUsername,
new { id = "uName_change" })
#Html.ValidationMessageFor(p => model.Part1.NewUsername)
return View(model);
}
I am using asp.net mvc 4 and I have the following scenario
Cities Places Events
------ ------------------
City 1 |
City 2 |
|
The left navigation (cities) list all of the cities in database. Places and Events also are links to action methods.
<li>#Html.ActionLink("Places", "Places", null, new{id="placeslink"})</li>
<li>#Html.ActionLink("Events", "Events", null, new{id="eventslink"})</li>
I am asynchronously loading Places and Events using the following script (jQuery)
$('#placeslink').click(function (event) {
event.preventDefault();
var url = $(this).attr('href');
$('#content').html(ajax_load).load(url);
});
$('#eventslink').click(function (event) {
event.preventDefault();
var url = $(this).attr('href');
$('#content').html(ajax_load).load(url);
});
Its is working fine and populates all the places (not city specific) and Events on the page from database when Places and Events links are clicked.
Now what I want to achieve is that when user click a city while viewing places, only the places in that city are displayed and if events are selected, the same city link should display the events in that city.
Similary if a city (e.g City 1) is selected and user click places, places in the selected city are displayed and if she clicks Events, events for the selected city are display.
I have the following action methods
public ActionResult Places()
{
if (Request.IsAjaxRequest())
{
....
return PartialView(model);
}
return View();
}
Its quite confusing and I cannot think of a single way how to generate appropriate links for City, places and events and achieve the above mentioned results.
Giving this a try, I would make the view model like this
public class PlacesAndEventsViewModel
{
public string LocationOption { get; set; } //places or events
public List<Place> Places { get; set; }
public List<Event> Events { get; set; }
public int? CityID { get; set; }
}
And my controller
//this is get
public ActionResult ShowLocations()
{
var model = new PlacesAndEventsViewModel();
model.CityID = null; //or any default value
model.LocationOption = "places"; //or any default value
model.Places = new List<Place>(); //or GetAllPlacesFromDB();
//You can do the same for events but I think you need one at a time
return View("ViewPlaces", model);
}
[HttpPost]
public ActionResult ShowLocations(PlacesAndEventsViewModel model)
{
if(model.LocationOption == "places")
{
model.Places = GetAllPlacesByCity(model.CityID);
return View("ViewPlaces", model); //All these could be partial view
}
else if(model.LocationOption == "cities")
{
model.Events = GetAllEventsByCity(model.CityID);
return View("ViewEvents", model); //All these could be partial view
}
else
{
return View("ViewPlaces", model); //All these could be partial view
}
}
You might need to change your Ajax to $.ajax()
$.ajax({
url: '#Url.Action("ShowLocation"),
data: { LocationOption: '#Model.LocationOption', CityID: #Model.CityID }
});