LINQ Extract data from website using HTMLAgilityPack - linq

I'm using C# HTMLAgilityPack to extract the item name, prices & currency symbol from a chinese website: https://meadjohnson.world.tmall.com/search.htm?search=y&orderType=defaultSort&s‌​cene=taobao_shop. Here's a gist of what the html looks like:
<div class="SaleItems">
<dl class="item ">
<dt class="photo"></dt>
<dd class="detail">
<a class="item-name">iPad</a>
<div class="price-area">
<span class="symbol">USD</span>
<span class="price">379</span>
</div>
</dd>
</dl>
<dl class="item ">
<dt class="photo"></dt>
<dd class="detail">
<a class="item-name">iPod</a>
<div class="price-area">
<span class="symbol">CAD</span>
<span class="price">139</span>
</div>
</dd>
</dl>
</div>
So far, this is what my program looks like.
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls
| SecurityProtocolType.Tls11
| SecurityProtocolType.Tls12
| SecurityProtocolType.Ssl3;
var htmlDocument = htmlWeb.Load(html);
var sItems = doc.DocumentNode.Descendants("SaleItems");
foreach (var item in sItems)
{
var data = new {
Currency = item["symbol"].InnerText,
Price = item["price"].InnerText,
};
}
This doesn't work. How can I fix what I'm doing wrong?

You can extract your data this way:
var input = #"<div class='SaleItems'>
<dl class='item '>
<dt class='photo'></dt>
<dd class='detail'>
<a class='item-name'>iPad</a>
<div class='price-area'>
<span class='symbol'>USD</span>
<span class='price'>379</span>
</div>
</dd>
</dl>
<dl class='item '>
<dt class='photo'></dt>
<dd class='detail'>
<a class='item-name'>iPod</a>
<div class='price-area'>
<span class='symbol'>CAD</span>
<span class='price'>139</span>
</div>
</dd>
</dl>
</div>";
var html = new HtmlDocument();
html.LoadHtml(input);
var root = html.DocumentNode;
var list = new List<Data>();
foreach (var node in root.Descendants("dl"))
{
var currency = node.Descendants()
.Where(n => n.GetAttributeValue("class", "").Equals("symbol")).FirstOrDefault().InnerText;
var price = node.Descendants()
.Where(n => n.GetAttributeValue("class", "").Equals("price")).FirstOrDefault().InnerText;
list.Add(new Data { Currency = currency, Price = price});
}
public class Data
{
public string Currency { get; set; }
public string Price { get; set; }
}
Or you can use query expression instead the foreach part:
var list = (from node in root.Descendants("dl")
let currency = node.Descendants().Where(n => n.GetAttributeValue("class", "").Equals("symbol")).FirstOrDefault().InnerText
let price = node.Descendants().Where(n => n.GetAttributeValue("class", "").Equals("price")).FirstOrDefault().InnerText
select new Data {Currency = currency, Price = price}).ToList();

The exact error is that in the foreach() block "item" is a variable of HtmlNode type but you are trying to "indexing" it. Instead of this you should use
item.Descendants("symbol")
or
item.SelectSingleNode(".//span[#class='symbol']");
Or You can use this code:
var document = new HtmlWeb();
var root = document.Load(url);
var data = new List<Item>();
foreach (var item in root.DocumentNode.SelectNodes("//dl"){
var name = item.SelectSingleNode(".//a[#class='item-name']").InnerText;
var price = item.SelectSingleNode(".//span[#class='price']").InnerText;
var symbol = item.SelectSingleNode(".//span[#class='symbol']").InnerText;
data.Add(new Item(){ Name = name, Price = price, Symbol = symbol });
}
public class Item{
public string Name;
public int Price;
public string Symbol;
}

Related

Bind multiple Dropdowns and retrieve user selction at postback

I'm working on an MVC Core form where a requester has to define some approvers for his application. When preparing the model for the Get request, I first get the roles for the approvers. Currently, there are always four roles returned:
Category Head
Governance Head
Concessions VP
Commercial EVP
And here is the HttpGet:
[HttpGet]
public async Task<IActionResult> Create()
{
// omitted for brevity...
// Get the SystemRole models (4 models will be returned)
model.ApprovingRoles = (await serviceLookup.GetAllRolesAsync(ct)).ToList();
}
The SystemRoleModel is simply:
public class SystemRoleModel
{
public int Id { get; set; }
public string Name { get; set; }
public bool Active { get; set; }
}
The view is composed of EditorTemplate as follows:
Create.cshtml -> LetterEditor.cshtml -> LetterAttachmentEditor.cshtml
Create.cshtml:
#model LetterModel
#{
ViewData["Title"] = "Create RL";
}
#Html.EditorFor(m => m, "LetterEditor", new { ShowApprovers = "1", ShowAttachments = "1", ShowButtons = "1" } )
LetterEditor.cshtml:
#model LetterModel
...
<div class="panel-body">
#await Html.PartialAsync("EditorTemplates/LetterAttachmentEditor", new LetterAttachmentUploadViewModel { IsBusy = false, LetterGuid = Model.IdCode.ToString() })
</div>
...
And finally, LetterAttachmentEditor.cshtml:
#model IList<SystemRoleModel>
#for (var i = 0; i < Model.Count; i++)
{
var index = i;
var title = Model[index].Name;
<div class="row">
<div class="col-lg-2 mt-3">
#Html.Label("LetterApprover[" + index + "]", title, new { #class = "control-label" })
</div>
<div class="col-lg-4">
#(Html.Kendo().DropDownList().Name("LetterApprover[" + index + "]")
.DataValueField(nameof(SystemUserModel.Id))
.DataTextField(nameof(SystemUserModel.EmployeeName))
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetUsersByRoleId", "Api", new { roleId = Model[index].Id });
}).ServerFiltering(true);
})
)
</div>
<div class="col-lg-6">
<span asp-validation="" class="text-danger"></span>
#Html.ValidationMessage("LetterApprover[" + index + "]", $"An approver as a {title} is required", new { #class = "text-danger" })
</div>
</div>
}
Also, LetterModel.cs:
public class LetterModel
{
public LetterModel()
{
Approvers = new List<LetterApproverModel>();
}
// omitted for brevity...
public IList<SystemRoleModel> ApprovingRoles { get; set; } = new List<SystemRoleModel>();
}
Now, with that all out of the way, here is the final rendered dropdown (minus the kendo fluff):
<input id="ApprovingRoles_LetterApprover_0_" name="ApprovingRoles.LetterApprover[0]" required="required" type="text" validationmessage="..." data-role="dropdownlist">
<input id="ApprovingRoles_LetterApprover_1_" name="ApprovingRoles.LetterApprover[1]" required="required" type="text" validationmessage="..." data-role="dropdownlist">
<input id="ApprovingRoles_LetterApprover_2_" name="ApprovingRoles.LetterApprover[2]" required="required" type="text" validationmessage="..." data-role="dropdownlist">
<input id="ApprovingRoles_LetterApprover_3_" name="ApprovingRoles.LetterApprover[3]" required="required" type="text" validationmessage="..." data-role="dropdownlist">
If the user submits this form, I need to receive a list of selected IDs from this array of dropdowns. I followed an anti-pattern, so I'm hoping the MVC binding will do its magic here. I just need to figure out the name of the model property that I should add of type List<string>.
How about try to change the name into name="LetterApprover[0]" and name="LetterApprover[1]" and name="LetterApprover[2]" and name="LetterApprover[3]" .
Then you could bind to List<string> LetterApprover
Update
Name is auto-appended by MVC due to sub-editor
How about add js codes to change the input name when you submit the form?
I try it like below, I first add class="form-control" to dropdownlist, add id="save" to button, then:
<script>
var items = document.getElementsByClassName("form-control");
$('#save').click(function () {
for (var i = 0; i < items.length; i++)
{
items[i].setAttribute("name", "LetterApprover")
}
});
</script>
Then bind to List<string> LetterApprover.
I was able to bind the selected values to a model's property upon submission by modifying the prefix added by the MVC engine:
#using DACRL.Domain.Models.BusinessObjects
#model IList<DACRL.Domain.Models.BusinessObjects.SystemRoleModel>
#{
ViewData.TemplateInfo.HtmlFieldPrefix = "";
}
#for (var i = 0; i < Model.Count; i++)
{
var index = i;
var name = "SelectedApprover[" + index + "]";
var title = Model[index].Name;
<div class="row">
<div class="col-lg-2 mt-2">
#Html.Label(name, title, new { #class = "control-label" })
</div>
<div class="col-lg-4">
#(Html.Kendo().DropDownList().Name(name)
.Size(ComponentSize.Medium).Rounded(Rounded.Medium).FillMode(FillMode.Outline)
.HtmlAttributes(new { style = "width: 100%" })
.DataValueField(nameof(SystemUserModel.Identifier))
.DataTextField(nameof(SystemUserModel.EmployeeName))
.OptionLabel("Select " + title).Filter(FilterType.Contains)
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetUsersByRoleId", "Api", new { roleId = Model[index].Id, sequence = index + 1 });
}).ServerFiltering(true);
})
.Height(500))
</div>
<div class="col-lg-6">
<span asp-validation="" class="text-danger"></span>
#Html.ValidationMessage(name, $"An approver as a {title} is required", new { #class = "text-danger mt-2" })
</div>
</div>
}
The line ViewData.TemplateInfo.HtmlFieldPrefix = ""; allowed me to control the naming and the binding started workinfg

Multi Select Values Not Saving on User Create

I am trying to save a multi select list on my user create in MVC 5, but the values are not saving. Values are saving only in edit. For some reason it's not working on create and it seems the issue is tied to the identity user. I have the same method implemented in a different controller for another entity and it's working fine.
I am trying to assign multiple health professionals to a user in the below code. I am not getting any errors or a break on save, it just doesn't save the values.
Can anyone please have a look at my code and give me a solution to this problem.
Here is my controller code relevant to creating a user:
public ActionResult Create()
{
PopulateDepartmentsDropDownList();
PopulateSuperiorsDropDownList();
// Show a list of available groups:
ViewBag.GroupsList = new SelectList(this.GroupManager.Groups, "Id", "Name");
var applicationUser = new ApplicationUser();
applicationUser.HealthProfessionals = new List<HealthProfessional>();
PopulateAssignedHealthProfessionals(applicationUser);
return View();
}
[HttpPost]
public async Task<ActionResult> Create([Bind(Exclude = "ProfilePicture")]RegisterViewModel userViewModel, ApplicationUser applicationUser, string[] selectedHealthProfessionals, params string[] selectedGroups)
{
if (selectedHealthProfessionals != null)
{
applicationUser.HealthProfessionals = new List<HealthProfessional>();
foreach (var healthProfessional in selectedHealthProfessionals)
{
var healthProfessionalToAdd = db.HealthProfessionals.Find(int.Parse(healthProfessional));
applicationUser.HealthProfessionals.Add(healthProfessionalToAdd);
}
}
if (ModelState.IsValid)
{
// To convert the user uploaded Photo as Byte Array before save to DB
byte[] imageData = null;
if (Request.Files.Count > 0)
{
HttpPostedFileBase poImgFile = Request.Files["UserPhoto"];
using (var binary = new BinaryReader(poImgFile.InputStream))
{
imageData = binary.ReadBytes(poImgFile.ContentLength);
}
}
var user = new ApplicationUser
{
UserName = userViewModel.Email,
FirstName = userViewModel.FirstName,
LastName = userViewModel.LastName,
Position = userViewModel.Position,
DepartmentID = userViewModel.DepartmentID,
SuperiorID = userViewModel.SuperiorID,
OfficeNumber = userViewModel.OfficeNumber,
CellNumber = userViewModel.CellNumber,
Email = userViewModel.Email
};
//Here we pass the byte array to user context to store in db
user.ProfilePicture = imageData;
var adminresult = await UserManager
.CreateAsync(user, userViewModel.Password);
//Add User to the selected Groups
if (adminresult.Succeeded)
{
if (selectedGroups != null)
{
selectedGroups = selectedGroups ?? new string[] { };
await this.GroupManager
.SetUserGroupsAsync(user.Id, selectedGroups);
}
return RedirectToAction("Users");
}
}
ViewBag.Groups = new SelectList(await RoleManager.Roles.ToListAsync(), "Id", "Name");
PopulateDepartmentsDropDownList(userViewModel.DepartmentID);
PopulateSuperiorsDropDownList(userViewModel.SuperiorID);
PopulateAssignedHealthProfessionals(applicationUser);
return View(applicationUser);
}
private void PopulateAssignedHealthProfessionals(ApplicationUser applicationUser)
{
var allHealthProfessionals = db.HealthProfessionals;
var userHealthProfessionals = new HashSet<int>(applicationUser.HealthProfessionals.Select(i => i.HealthProfessionalID));
var viewModel = new List<AssignedHealthProfessionals>();
foreach (var healthProfessional in allHealthProfessionals)
{
viewModel.Add(new AssignedHealthProfessionals
{
HealthProfessionalID = healthProfessional.HealthProfessionalID,
HealthProfessionalName = healthProfessional.Name,
HealthProfessionalSurname = healthProfessional.Surname,
Assigned = userHealthProfessionals.Contains(healthProfessional.HealthProfessionalID)
});
}
ViewBag.HealthProfessionals = viewModel;
}
Here is my create view:
#model MyApp.Models.RegisterViewModel
#{
ViewBag.Title = "Create User";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<link href="#Url.Content("~/Content/CSS/dropify.min.css")" rel="stylesheet" type="text/css" />
<div class="m-grid__item m-grid__item--fluid m-wrapper">
<div class="m-subheader ">
<div class="d-flex align-items-center">
<div class="mr-auto">
<h3 class="m-subheader__title m-subheader__title--separator">
Add User
</h3>
<ul class="m-subheader__breadcrumbs m-nav m-nav--inline">
<li class="m-nav__item m-nav__item--home">
<a href="#Url.Action("Dashboard","Home")" class="m-nav__link m-nav__link--icon">
<i class="m-nav__link-icon la la-home"></i>
</a>
</li>
<li class="m-nav__separator">
-
</li>
<li class="m-nav__item">
<a href="#Url.Action("Users","UserManagement")" class="m-nav__link">
<span class="m-nav__link-text">
Users
</span>
</a>
</li>
</ul>
</div>
<div>
</div>
</div>
</div>
#using (Html.BeginForm("Create", "UserManagement", FormMethod.Post, new { #class = "m-form m-form--fit m-form--label-align-right", role = "form", enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<div class="m-content">
<div class="m-portlet m-portlet--mobile">
<div class="m-portlet__head">
<div class="m-portlet__head-caption">
<div class="m-portlet__head-title">
<h3 class="m-portlet__head-text">
User Details
</h3>
</div>
</div>
</div>
<div class="m-portlet__body">
<div class="m-form__section m-form__section--first">
<div class="row">
<div class="col-lg-4">
<div class="form-group">
<label>
Email Address
</label>
#Html.TextBoxFor(m => m.Email, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Email, "", new { #class = "text-danger" })
</div>
</div>
<div class="col-lg-4">
<div class="form-group">
<label>
First Name
</label>
#Html.TextBoxFor(m => m.FirstName, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.FirstName, "", new { #class = "text-danger" })
</div>
</div>
<div class="col-lg-4">
<div class="form-group">
<label>
Last Name
</label>
#Html.TextBoxFor(m => m.LastName, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.LastName, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="row">
<div class="col-lg-4">
<div class="form-group">
<label>
Position
</label>
#Html.TextBoxFor(m => m.Position, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Position, "", new { #class = "text-danger" })
</div>
</div>
<div class="col-lg-4">
<div class="form-group">
<label>
Department
</label>
#Html.DropDownList("DepartmentID", null, "Choose Department", htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.DepartmentID, "", new { #class = "text-danger" })
</div>
</div>
<div class="col-lg-4">
<div class="form-group">
<label>
Superior
</label>
#Html.DropDownList("SuperiorID", null, "Choose Superior", htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.SuperiorID, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="row">
<div class="col-lg-6">
<div class="form-group">
<label>
Password
</label>
#Html.PasswordFor(m => m.Password, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Password, "", new { #class = "text-danger" })
</div>
</div>
<div class="col-lg-6">
<div class="form-group">
<label>
Confirm Password
</label>
#Html.PasswordFor(m => m.ConfirmPassword, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.ConfirmPassword, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="row">
<div class="col-lg-6">
<div class="form-group">
<label>
Office Number
</label>
#Html.TextBoxFor(m => m.OfficeNumber, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.OfficeNumber, "", new { #class = "text-danger" })
</div>
</div>
<div class="col-lg-6">
<div class="form-group">
<label>
Cell Number
</label>
#Html.TextBoxFor(m => m.CellNumber, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.CellNumber, "", new { #class = "text-danger" })
</div>
</div>
</div>
<div class="row">
<div class="col-lg-6">
<div class="form-group">
<label>
User Groups
</label>
<div class="m-checkbox-list">
#foreach (var item in (SelectList)ViewBag.GroupsList)
{
<label class="m-checkbox m-checkbox--success">
<input type="checkbox" name="selectedGroups" value="#item.Value">
#Html.Label(item.Text, new { #class = "control-label" })
<span></span>
</label>
}
</div>
</div>
</div>
<div class="col-lg-6">
<div class="form-group">
<label>
Health Professionals
</label>
<div class="m-checkbox-list">
#{
int cnt = 0;
List<MyApp.ViewModels.AssignedHealthProfessionals> healthProfessionals = ViewBag.HealthProfessionals;
foreach (var healthProfessional in healthProfessionals)
{
if (cnt++ % 3 == 0)
{
}
<label class="m-checkbox m-checkbox--success">
<input type="checkbox" name="selectedHealthProfessionals" value="#healthProfessional.HealthProfessionalID" #(Html.Raw(healthProfessional.Assigned ? "checked=\"checked\"" : ""))>
#Html.Label(healthProfessional.HealthProfessionalName, new { #class = "control-label" }) #Html.Label(healthProfessional.HealthProfessionalSurname, new { #class = "control-label" })
<span></span>
</label>
}
}
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div class="form-group">
<label>
Profile Picture
</label>
<input type="file" name="UserPhoto" id="fileUpload" accept=".png,.jpg,.jpeg,.gif,.tif" class="dropify" />
</div>
</div>
</div>
</div>
</div>
</div>
<div class="m-portlet__body">
<!-- Form Actions Start -->
<div class="m-portlet">
<div class="m-portlet__head">
<div class="m-portlet__head-caption">
<div class="m-portlet__head-title">
<h3 class="m-portlet__head-text">
Actions
</h3>
</div>
</div>
</div>
<div class="m-portlet__foot m-portlet__foot--fit">
<div class="m-form__actions">
<input type="submit" class="btn btn-accent m-btn m-btn--custom m-btn--icon m-btn--air m-btn--pill" value="Save" />
#Html.ActionLink("Cancel", "Users", null, new { #class = "btn m-btn--pill m-btn--air btn-brand m-btn m-btn--custom" })
</div>
</div>
</div>
<!-- Form Actions End -->
</div>
</div>
}
</div>
<script src="#Url.Content("~/Scripts/jquery.min.js")"></script>
<script src="#Url.Content("~/Scripts/dropify.min.js")"></script>
<script>
$(document).ready(function () {
// Basic
$('.dropify').dropify();
// Translated
$('.dropify-fr').dropify({
messages: {
default: 'Glissez-déposez un fichier ici ou cliquez',
replace: 'Glissez-déposez un fichier ou cliquez pour remplacer',
remove: 'Supprimer',
error: 'Désolé, le fichier trop volumineux'
}
});
// Used events
var drEvent = $('#input-file-events').dropify();
drEvent.on('dropify.beforeClear', function (event, element) {
return confirm("Do you really want to delete \"" + element.file.name + "\" ?");
});
drEvent.on('dropify.afterClear', function (event, element) {
alert('File deleted');
});
drEvent.on('dropify.errors', function (event, element) {
console.log('Has Errors');
});
var drDestroy = $('#input-file-to-destroy').dropify();
drDestroy = drDestroy.data('dropify')
$('#toggleDropify').on('click', function (e) {
e.preventDefault();
if (drDestroy.isDropified()) {
drDestroy.destroy();
} else {
drDestroy.init();
}
})
});
</script>
Here is the controller for the edit function which works:
public async Task<ActionResult> Edit(int id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
ApplicationUser applicationUser = db.Users.Include(h => h.HealthProfessionals).Where(h => h.Id == id).Single();
PopulateAssignedHealthProfessionals(applicationUser);
var user = await UserManager.FindByIdAsync(id);
if (user == null)
{
return HttpNotFound();
}
// Display a list of available Groups:
var allGroups = this.GroupManager.Groups;
var userGroups = await this.GroupManager.GetUserGroupsAsync(id);
var model = new EditUserViewModel()
{
Id = user.Id,
Email = user.Email,
FirstName = user.FirstName,
LastName = user.LastName,
Position = user.Position,
DepartmentID = user.DepartmentID,
SuperiorID = user.SuperiorID,
OfficeNumber = user.OfficeNumber,
CellNumber = user.CellNumber
};
foreach (var group in allGroups)
{
var listItem = new SelectListItem()
{
Text = group.Name,
Value = group.Id,
Selected = userGroups.Any(g => g.Id == group.Id)
};
model.GroupsList.Add(listItem);
}
PopulateDepartmentsDropDownList(user.DepartmentID);
PopulateSuperiorsDropDownList(user.SuperiorID);
return View(model);
}
private void PopulateAssignedHealthProfessionals(ApplicationUser applicationUser)
{
var allHealthProfessionals = db.HealthProfessionals;
var userHealthProfessionals = new HashSet<int>(applicationUser.HealthProfessionals.Select(i => i.HealthProfessionalID));
var viewModel = new List<AssignedHealthProfessionals>();
foreach (var healthProfessional in allHealthProfessionals)
{
viewModel.Add(new AssignedHealthProfessionals
{
HealthProfessionalID = healthProfessional.HealthProfessionalID,
HealthProfessionalName = healthProfessional.Name,
HealthProfessionalSurname = healthProfessional.Surname,
Assigned = userHealthProfessionals.Contains(healthProfessional.HealthProfessionalID)
});
}
ViewBag.HealthProfessionals = viewModel;
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit([Bind(Include = "Email,Id,FirstName,LastName,Position,DepartmentID,SuperiorID,OfficeNumber,CellNumber", Exclude = "ProfilePicture")] EditUserViewModel editUser, ApplicationUser applicationUser, int? id, string[] selectedHealthProfessionals, params string[] selectedGroups)
{
if (ModelState.IsValid)
{
// To convert the user uploaded Photo as Byte Array before save to DB
byte[] imageData = null;
if (Request.Files.Count > 0)
{
HttpPostedFileBase poImgFile = Request.Files["UserPhoto"];
using (var binary = new BinaryReader(poImgFile.InputStream))
{
imageData = binary.ReadBytes(poImgFile.ContentLength);
}
}
var user = await UserManager.FindByIdAsync(editUser.Id);
if (user == null)
{
return HttpNotFound();
}
var applicationUserToUpdate = db.Users.Include(h => h.HealthProfessionals).Where(h => h.Id == id).Single();
if (TryUpdateModel(applicationUserToUpdate, "",
new string[] { }))
{
try
{
UpdateUserHealthProfessionals(selectedHealthProfessionals, applicationUserToUpdate);
db.SaveChanges();
return RedirectToAction("Users");
}
catch (RetryLimitExceededException /* dex */)
{
//Log the error (uncomment dex variable name and add a line here to write a log.
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
}
}
PopulateAssignedHealthProfessionals(applicationUserToUpdate);
// Update the User:
user.UserName = editUser.Email;
user.Email = editUser.Email;
user.FirstName = editUser.FirstName;
user.LastName = editUser.LastName;
user.Position = editUser.Position;
user.DepartmentID = editUser.DepartmentID;
user.SuperiorID = editUser.SuperiorID;
user.OfficeNumber = editUser.OfficeNumber;
user.CellNumber = editUser.CellNumber;
//Here we pass the byte array to user context to store in db
user.ProfilePicture = imageData;
await this.UserManager.UpdateAsync(user);
// Update the Groups:
selectedGroups = selectedGroups ?? new string[] { };
await this.GroupManager.SetUserGroupsAsync(user.Id, selectedGroups);
return RedirectToAction("Users");
}
ModelState.AddModelError("", "Something failed.");
PopulateDepartmentsDropDownList(editUser.DepartmentID);
PopulateSuperiorsDropDownList(editUser.SuperiorID);
return View();
}
It's something strange with parameters in your methods.
Best way is to pass user object as parameter.
https://stackoverflow.com/a/18005264/2114398
For quick fix you can update multi-select parameter manually, by removing selectedHealthProfessionals and selectedGroups parameters from method and then initialize them as local variables
[HttpPost]
public async Task<ActionResult> Create([Bind(Exclude = "ProfilePicture")]RegisterViewModel userViewModel, ApplicationUser applicationUser)
{
var selectedGroups = (Request.Form["selectedGroups"] ?? "").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
var selectedHealthProfessionals = (Request.Form["selectedHealthProfessionals"] ?? "").Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
applicationUser.HealthProfessionals = new List<HealthProfessional>();
foreach (var healthProfessional in selectedHealthProfessionals)
{
var healthProfessionalToAdd = db.HealthProfessionals.Find(int.Parse(healthProfessional));
applicationUser.HealthProfessionals.Add(healthProfessionalToAdd);
}
if (ModelState.IsValid)
{
...

how populate a Partial View on page load using ajax in asp.net mvc with some query?

I'm working on Asp.net MVC 5 project . I have below code and it works fine without error , my problem is : in page load showed all of records , I want to show a specific record . How can I do it ?
controller :
public ActionResult GoodDetails(int id)
{
HomeVM vm = new HomeVM();
var goodDetails = db.GoodDetails.Where(p => p.FKSubGoods == id).ToList();
vm.GoodDetails = goodDetails;
return View(vm);
}
public PartialViewResult GoodDetailsAjax(int id)
{
HomeVM vm = new HomeVM();
var GoodDetailsAjax = db.GoodDetails.Where(p => p.DetailsGoodID == id).ToList();
vm.GoodDetails = GoodDetailsAjax;
return PartialView("_GoodDetailsAjax", vm);
}
_GoodDetailsAjax.cshtml :
#model NP1.ViewModels.HomeVM
<div>
#foreach (var item in Model.GoodDetails)
{
<img class="img-responsive" src="#Url.Content(item.DetailsImage1.ToString())">
<img class="img-responsive" src="#Url.Content(item.DetailsImage2.ToString())">
<img class="img-responsive" src="#Url.Content(item.DetailsImage3.ToString())">
<img class="img-responsive" src="#Url.Content(item.DetailsImage3.ToString())">
}
</div>
I added #{Html.RenderPartial("_GoodDetailsAjax", Model);} to Target div to show a record on page load , but it shows all records and I don't know how write a specific record. I wrote some codes instead of Model but they didn't work .
Thanks for any help .
<div>
#foreach (var item1 in Model.GoodDetails)
{
#Ajax.ActionLink("LinkText", "GoodDetailsAjax", new { id = #item1.DetailsGoodID }, new AjaxOptions()
{
HttpMethod = "GET",
UpdateTargetId = "DivAjax",
InsertionMode = InsertionMode.Replace
}
)
<input type="image" src="#Url.Content(item1.DetailsSmallImage1.ToString())">
}
</div>
<div id="DivAjax">
#{Html.RenderPartial("_GoodDetailsAjax", Model);}
</div>

View with ViewModel

I have one ViewModels which contain other ViewModels
public class AllProductsViewModel
{
public ICollection<ProductSearchViewModel> ProductSearch { get; set; }
public ICollection<ProductRentViewModel> ProductRent { get; set; }
public ICollection<ProductBuyViewModel> ProductBuy { get; set; }
}
My Controller is:
public ActionResult Index()
{
var listOfProductsBuy = db.ProductsBuy.Select(x => new ProductBuyViewModel
{
Id = x.Id,
Title = x.Title,
MasterImageUrl = x.Images.FirstOrDefault().Url,
Price = x.Price,
Values = x.Value,
}).ToList();
var listOfProductsRent = db.ProductsRent.Select(y => new ProductRentViewModel
{
Id = y.Id,
Title = y.Title,
MasterImageUrl = y.ImagesRent.FirstOrDefault().Url,
Price = y.Price,
Values = y.Value,
}).ToList();
var listOfProductsSearch = db.ProductSearches.Select(z => new ProductSearchViewModel
{
Id = z.Id,
Title = z.Title,
MasterImageUrl = z.ImagesSearch.FirstOrDefault().Url,
Price = z.Price,
Values = z.Value,
}).ToList();
var viewModel = new AllProductsViewModel { ProductBuy = listOfProductsBuy, ProductRent = listOfProductsRent, ProductSearch = listOfProductsSearch };
return View(viewModel);
}
}
And my View:
#model IEnumerable<RealEstateMarket.ViewModels.AllProductsViewModel>
#{
ViewBag.Title = "Home Page";
}
<br />
<div class="row">
<div class="col-md-3">
#foreach (var item in Model)
{
<h3>#item.ProductBuy.Select(x => x.Title)</h3>
<div>
<img height="100" width="120" class="thumbnail" src="#item.ProductBuy.Select(x => x.MasterImageUrl )" />
</div>
<h3>#item.ProductBuy.Select(x => x.Price) #item.ProductBuy.Select(x => x.Values.Currency)</h3>
}
</div>
</div>
A want to take the fields of ProductBuyViewModel,ProductRentViewModel, ProductSearchViewModel
When I start this code i get the error: The model item passed into the dictionary is of type 'RealEstateMarket.ViewModels.AllProductsViewModel', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[RealEstateMarket.ViewModels.AllProductsViewModel]'.
change this
#model IEnumerable<RealEstateMarket.ViewModels.AllProductsViewModel>
to
#model RealEstateMarket.ViewModels.AllProductsViewModel
and then you can access to your list
<div class="col-md-3">
#for (int index=0;index<Model.ProductSearch.Count();index++)
{
<h3>#Model.ProductSearch[index].Title</h3>
<div>
<img height="100" width="120" class="thumbnail" src="#Model.ProductSearch[index].MasterImageUrl )" />
</div>
<h3>#Model.ProductSearch[index].Price #Model.ProductSearch[index].Values.Currency)</h3>
}
</div>

Magento sidebar parent curent category and subcategory permanent

I want to add to sidebar the CURENT category and subcategory of the products, but to be the same even if i am entering a subcategory. Right now i have this script for left menu ( sidebar )
<?php $_menu = $this->renderCategoriesMenuHtml(0,'level-top') ?>
<?php if($_menu): ?>
<div class="block block-menu-navleft">
<div class="block-title">
<strong><span><?php echo $this->__('Category') ?></span></strong>
</div>
<div class="block-content">
<ul id="nav1" class="menu-left">
<?php echo $_menu ?>
</ul>
</div>
</div>
<?php endif ?>
<script type="text/javascript">
var lis=$$('#nav1 li.parent');
lis.each(function(li) {
var dt = new Element('dt');
var dd = new Element('dd');
var a = li.down(0);
var ul = li.down(2);
dt.insert(a);
dd.insert(ul);
li.insert(dt,{position:top});
li.insert(dd);
});
jQuery('#nav1 li.parent dd ul ').hide();
jQuery('#nav1 dt a').click(function() {
jQuery('.td_active').removeClass('td_active');
var string = jQuery(this).parent().parent().parent().parent().parent().attr('class');
if(string.indexOf('parent')!=-1)
{
jQuery(this).parent().parent().parent().parent().parent().addClass('td_active');
jQuery(this).parent().parent().parent().css("display","block");
jQuery(this).parent().parent().find('ul').slideUp('slow');
}
else
{
jQuery('#nav1 li.parent dd ul:visible').slideUp('slow');
}
jQuery(this).parent().parent().addClass('td_active').next().slideDown('fast');
if(jQuery(this).parent().parent().find('ul').css('display')=='block')
{
jQuery(this).parent().parent().removeClass('td_active');
}
jQuery(this).parent().parent().children().children(':first-child').css("display","block");
return false;
});
</script>
This script works fine but it shows me ALL FATHER CATEGORIES and SUBCATEGORIES. I want to show me just the CURENT CATEGORY AND SUBCATEGORY.
!example image1
Use this :
$menu = $this->drawItem(Mage::registry('current_category'),Mage::registry('current_category')->getLevel());
instead of
$_menu = $this->renderCategoriesMenuHtml(0,'level-top')
To handle all case you should consider do something like :
$menu = (isset(Mage::registry('current_category'))?$this->drawItem(Mage::registry('current_category'),Mage::registry('current_category')->getLevel()):$this->renderCategoriesMenuHtml(0,'level-top');

Resources