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.
Related
In my Xamarin app, there is a Picker which gets the Bank List from Database, and this DB gets the Bank details through an API.
Everything works fine, but now, I want to update the DB, if the new Banks are added in API, I want to add them in the existing database.
I wrote this small code, but the problem is, it first output all the existing records from the database and then print the new records, many times as the total amount of records e.g. (if there are ten records, it will print every record ten times).
ViewModel.cs
// Load all Banks into a List
var getBanks = await App.Database.GetBankAsync();
// Update the Bank Details where new Banks doesn't exist in the Database
List<Bank> updateBanks = new List<Bank>();
foreach (Banks i in obj.banks)
{
foreach (var record in getBanks.Where(c => c.Name != i.alias.name))
{
updateBanks.Add(new Bank { Name = i.alias.name, Status = "Not Registered" });
}
}
foreach (var bank in updateBanks)
{
await App.Database.SaveBankAsync(bank);
}
// Load all Banks into a List
var getBanksUpdated = await App.Database.GetBankAsync();
// Load the Banks whose Status is "Not Registered"
foreach (var record in getBanks.Where(c => c.Status == "Not Registered")
{
_bankList.Add(record);
}
public class Alias
{
public string name { get; set; }
}
public class Banks
{
public Alias alias { get; set; }
public string id { get; set; }
}
public class RootObject
{
public List<Banks> banks { get; set; }
}
Data getting through API
{
success: true,
banks: [
{
alias: {
name: "Bank 1",
Address: "Earth"
},
endpoint: {
uri: "http://127.0.0.1:0000"
},
state: "Registered",
createdAtUtc: "2021-01-19T13:55:12.2318662",
updatedAtUtc: "2021-01-19T13:55:14.9944042"
},
]
}
Code to get the data from API
HttpClient httpClient = new HttpClient(new NativeMessageHandler());
Uri getDataBanks = new Uri(string.Format("http://127.0.0.1:0000/Banks"));
HttpResponseMessage restponseBanks = await httpClient.GetAsync(getDataBanks);
string contentBanks = await restponseBanks.Content.ReadAsStringAsync();
RootObject obj = JsonConvert.DeserializeObject<RootObject>(contentBanks);
// get the names of all existing banks
List<string> names= obj.banks.Select(u => u.Name).ToList();
// get the names of all banks taken from the API
List<string> names_new= getBanks.Select(u => u.Name).ToList();
foreach (var record in names_new)
{
//check if the bank is exists or not
if(! names.contains(record)
{
updateBanks.Add(new Bank { Name = record.alias.name, Status = "Not Registered" });
}
}
I'm not aware of your data, but you you have too foreach loops and you are checking the whole collection in every loop. SO, it's possible, that your condition catches every account on every loop.
This is to submit a view that uses ajax to pull the data.
I am trying to retrieve an image from MongoDb GridFS bucket. The download operation works. But the issue is, the view model that I use has:
public User User { get; set; }
public List<IFormFile> ImageUpload { get; set; }
I get the user from the db context, and use that to identify the image from the bucket and I want to return it to the view from the controller.
The following is my controller code:
public IActionResult AddEditUser(int id = 0)
{
if (id == 0)
{
return View(new UserImgBinder());
}
else
{
var userImageId = _context.User.Where(x => x.UserId.Equals(id)).Select(y => y.AvatarImg).ToString();
var stream = ContextNew.ImagesBucket.OpenDownloadStream(new ObjectId(userImageId.ToBson()));
var contentType = stream.FileInfo.Metadata["ContentType"].AsString;
//File(stream, contentType);
IFormFile file = new FormFile(stream, 0, stream.Length,"","");
var UserImgBinder = new UserImgBinder
{
User = _context.User.Where(x => x.UserId.Equals(id)).FirstOrDefault(),
ImageUpload = file
};
return View(UserImgBinder);
}
}
Since ImageUpload is of type List and what I am trying to feed it is not a list I am getting error.
What should I write to solve this? Is this approach bad?
Please help.
Thanks.
Try code like:
var UserImgBinder = new UserImgBinder
{
User = _context.User.Where(x => x.UserId.Equals(id)).FirstOrDefault(),
ImageUpload = new List<IFormFile> {
file
}
};
I have an MVC Web Application which uses a form to get a postal code from the user, which then queries an external web service and returns a list of addresses to the view.
I had a previous issue whereby my model was static, therefore the data was being displayed to users on other clients, rather than being specific to each user. I have now got it so each individual user can query and get their list of addresses on the view (which isn't visible to anyone else) however, when the user refreshes the page or goes back, the data is lost.
I have some code on the page refresh which checks if the data is there and won't take the user to the start of the form, however on page refresh the model returns to null, hence it will always take them back to the beginning.
Any ideas? I ideally want to be able to use the data multiple times for the current user, but if they refresh and are say 90% through the form, they will lose the whole data. It seems like it should be easy but all of the examples I have tried haven't worked for my particular scenario.
Controller:
public class AssistedController : Controller
{
// GET: Assisted
AddressList model;
public ActionResult Index()
{
return View(model);
}
[HttpPost]
public ActionResult GetAddresses(string postcode)
{
model = new AddressList();
if (postcode == null || postcode == "")
{
return RedirectToAction("/Index/");
}
//call enviroweb web service
AddressWeb ew = new AddressWeb();
//extract address values from the XML returned from web service
XmlNode xml = ew.GetAddress(", , , , " + postcode);
foreach (XmlElement addressInfo in xml)
{
foreach (XmlElement teset in addressInfo["Addresses"])
{
//add each address item found to the list
model.listone.Add(new AddressResults {
FullAddress = teset["fulladdress"].InnerText,
Lat = teset["Lat"].InnerText,
Lon = teset["Long"].InnerText,
addLine1 = teset["addline1"].InnerText,
addLine2 = teset["addline2"].InnerText,
addLine3 = teset["addline3"].InnerText,
addLine4 = teset["addline4"].InnerText,
Town = teset["Town"].InnerText,
postcode = teset["postcode"].InnerText,
Ownership = teset["Ownership"].InnerText,
WeekNumber = teset["WeekNumber"].InnerText
});
}
}
//return the list and model back to the index view
return View("Index", model);
}
View:
<!--Use the model to return the data-->
#model AddressSearch.Models.AddressList
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#if (Model == null)
{
}
else
{
if (Model.listone.Count != 0)
{
//this section returns the items as options in the select if the list count is greater than 0.
foreach (var test in Model.listone)
{
<option value="#test.FullAddress">#test.FullAddress</option>
}
}
}
Model:
public class AddressList
{
public List<AddressResults> listone = new List<AddressResults>();
}
TempData in ASP.NET MVC can be used to store temporary data which can be used in the subsequent request. TempData will be cleared out after the completion of a subsequent request.
public class AssistedController : Controller
{
// GET: Assisted
AddressList model;
public ActionResult Index()
{
if (TemData.ContainsKey("address"))
{
model = TempData["address"] as AddressList;
}
return View(model);
}
[HttpPost]
public ActionResult GetAddresses(string postcode)
{
model = new AddressList();
if (postcode == null || postcode == "")
{
return RedirectToAction("/Index/");
}
if (TemData.ContainsKey("address"))
{
model = TempData["address"] as AddressList;
return View(model);
}
//call enviroweb web service
AddressWeb ew = new AddressWeb();
//extract address values from the XML returned from web service
XmlNode xml = ew.GetAddress(", , , , " + postcode);
foreach (XmlElement addressInfo in xml)
{
foreach (XmlElement teset in addressInfo["Addresses"])
{
//add each address item found to the list
model.listone.Add(new AddressResults
{
FullAddress = teset["fulladdress"].InnerText,
Lat = teset["Lat"].InnerText,
Lon = teset["Long"].InnerText,
addLine1 = teset["addline1"].InnerText,
addLine2 = teset["addline2"].InnerText,
addLine3 = teset["addline3"].InnerText,
addLine4 = teset["addline4"].InnerText,
Town = teset["Town"].InnerText,
postcode = teset["postcode"].InnerText,
Ownership = teset["Ownership"].InnerText,
WeekNumber = teset["WeekNumber"].InnerText
});
}
}
TempData["address"] = model;
//return the list and model back to the index view
return View("Index", model);
}
}
Refer this link to how to use
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
}
Got this repository code.
public IEnumerable<FollowedPerson> ReadFollowedPersonsById(int id, SPList list)
{
var item = list.GetItemById(id);
if (item == null)
{
return null;
}
var likedByCollection = (SPFieldUserValueCollection)item["LikedBy"];
if (likedByCollection == null)
{
return null;
}
var followers = new Collection<FollowedPerson>();
foreach (var liker in likedByCollection)
{
followers.Add(new FollowedPerson
{
Name = liker.User.Name,
ImageUrl = string.Empty //TODO Urls of users avatars
});
}
return followers;
}
I want to get the collection of users that liked some list item. Collection item looks like this:
public class FollowedPerson
{
public string Name { get; set; }
public string ImageUrl { get; set; }
}
Getting their names works fine but I don`t know how I can get their avatar images by theirs login names.
liker.User //does not contain any url of user`s image
You can get this info from user profile. You may read about how to work with it here: Work with user profiles in SharePoint 2013.
There is code snippet for retrieve all user profile properties:
// Replace the following placeholder values with the target SharePoint site and
// target user.
const string serverUrl = "http://serverName/";
const string targetUser = "domainName\\userName";
// Connect to the client context.
ClientContext clientContext = new ClientContext(serverUrl);
// Get the PeopleManager object and then get the target user's properties.
PeopleManager peopleManager = new PeopleManager(clientContext);
PersonProperties personProperties = peopleManager.GetPropertiesFor(targetUser);
// Load the request and run it on the server.
// This example requests only the AccountName and UserProfileProperties
// properties of the personProperties object.
clientContext.Load(personProperties, p => p.AccountName, p => p.UserProfileProperties);
clientContext.ExecuteQuery();
foreach (var property in personProperties.UserProfileProperties)
{
Console.WriteLine(string.Format("{0}: {1}",
property.Key.ToString(), property.Value.ToString()));
}