Html Agility Pack asp.net mvc Xpath - asp.net-mvc

I have this html:
Picture with html code
I need to show in my View : Бавария Майнц -2.25
I try write this:
HtmlDocument htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(
"https://www.parimatch.com/sport/futbol/germanija-bundesliga");
foreach (HtmlNode table in htmlDoc.DocumentNode.SelectNodes("//div[#id='oddsNote']/table/tbody"))
{
foreach (HtmlNode row in table.SelectNodes("tr"))
{
HtmlNodeCollection cells = row.SelectNodes("td");
if (cells == null)
{
continue;
}
foreach (HtmlNode cell in cells)
{
ViewBag.Results += cell.InnerText;
}
}
}
but my table always null. Where I have a mistake?
and what are the other options to output in View except Viewbag?
My HTML:
<div id ="z_container">
<div id = "Z_contentw">
<div id = "OddList">
<form name ="f1" id = "f1">
<div class = "container_grey">
<div class = "wrapper">
<table id = "4529899" class ="dt_twp">
<tbody class ="row1 processed">
<tr class ="bk">
<td> "02/03" <br> "21:00"</td>
<td class ="l"> <a class ="om" id ="a738">Bavaria Mainc</a></td>
<td> <b 3.5></td>
</tr>
</tbody>
<tbody class ="row2 processed">
<tr class ="bk">
<td> "03/03" <br> "19:00"</td>
<td class ="l"> <a class ="om" id ="a739">Roma Milan</a></td>
<td> <b 2.5></td>
</tr>
</tbody>
</table>
</div>
</div>
</form>
</div>
</div>
</div>
I need to show: 02/03 21:00 Bavaria Mainc 03/03 19:00 Roma Milan

Your xpath has an id that is not in the html you provided other than that
If you want the text in one line as you showed then it can be
var text = string.Join(" ", doc.DocumentNode.SelectNodes("//tr[#class='bk']//text()[normalize-space()]").Select(t=>t.InnerText));
If you want to model the data then use the indices of the td, the first one has the time the second has the teams so create a simple model
class FootballMatch
{
public string Time;
public string Teams;
}
and get the data using the following
var matches = doc.DocumentNode.SelectNodes("//tr[#class='bk']").
Select(tr => new FootballMatch() {
Time = string.Join(" ", tr.SelectNodes("./td[1]//text()").Select(t => t.InnerText)),
Teams = tr.SelectSingleNode("./td[2]//text()[normalize-space()]").InnerText,
});

Related

Merge different data with same Id in 'TR' tag in MVC view

This is my current structure in the view :
Now as per the above image, the Movie 'Avengers' is having same Movieid in my table, but different celebs like Scarlett,Robert, etc. But the records for 'Russo' & 'Scarlett' are placed in different Tr tag. How can i be able to move these two records in the same Tr below 'Robert Jr.'.
I have tried this, but this gives me the output in the image above :
<table class="table table-bordered" id="topicList">
<thead>
<tr><th data-priority="1"><span>Movies</span></th>
<th data-priority="3"><span>Roles</span></th></tr>
</thead>
<tbody>
#{ int movieid = 0; }
#foreach (var item in Model)
{
<tr>
<td class="topicTd">
#if (movieid != item.MovieId)
{
<div class="table_home">
<span>#item.MovieName</span>
</div>
}
#{ movieid = item.MovieId; }
</td>
<td>
<div id="roles">
<div class="img_div">
<div class="rolelistTooltip">
<a href="javascript:void(0);" class="hover right_div" data-trigger="focus" id="229759" role="button">
<img src="~/Content/0829.jpg" class="imgSquare img-responsive img-circle" alt="#item.CelebName">
</a>
</div>
</div>
<div class="content_img">
<h3><strong class="groupID11">#item.CelebName</strong></h3>
<p>
#item.RoleName
</p>
</div>
</div>
</td>
</tr>
}
</tbody>
This is the model :
Int MovieId, string MovieName, int celebId, string CelebName, int roleId, string RoleName

delete from model don't work correctly

i have a repeating table in razor mvc , my model is an array
#model Models.Event[]
when i delete any row , every thing is ok and i check data in break point...
but view can't render data correctly and always last row is deleted.
in my code, i want to delete row index 2 ... i give it as hard code , in controller and view true data is passed but at the end, in view (display page) , the last row is deleted and the row with index 2 is there again :(
i pass my model from an partial view to the main page.
here is my javascript codes:
<script type="text/javascript">
$(document)
.ready(function () {
$("#EventsTbl")
.on("click", "tbody .btn-delrow",
function () {
var deletedrow = $(this).closest("tr");
var index = 2; // deletedrow.attr("data-ownum");
var data = $("#edit-Event-form").serialize();
deleteEvent(data, index);
});
function deleteEvent(data,index) {
if (confirm("Do you want to delete product: " + index)) {
var postdata = data;
$.post('/Events/DeleteDetailRow', postdata,
function (response) {
$("#EventsTbl tbody").html(response);
});
}
}
});
</script>
and in controller we have :
[HttpPost]
public ActionResult DeleteDetailRow(Event[] model)
{
var list = new List<Event>(model);
list.RemoveAt(2);
return PartialView("AllDetailRows", list.ToArray());
}
"list" has true data after delete, but i don't know where is the problem. at AllDetailRows model has true data too.
here is my partial view code : (AllDetailRows)
#model Models.Event[]
#for (int i = 0; i < Model.Length; i++)
{
<tr data-rownum="#i">
<td class="input">
#Html.EditorFor(model => model[i].EventExp,new {value=Model?[i]?.EventExp})
#Html.ValidationMessageFor(model => model[i].EventExp, "", new { #class = "text-danger" })
</td>
<td>
<button class="btn btn-sm btn-danger btn-delrow" type="button">
<i class="fa fa-remove"></i>
</button>
</td>
</tr>
}
and this is my main view :
#model Models.Event[]
#* This partial view defines form fields that will appear when creating and editing entities *#
<fieldset>
<div>
<table class="table table-bordered table-striped" id="AdverseEventsTbl">
<thead>
<tr>
<th class="text-center or-bold" style="width: 10%">#Html.LabelFor(model => model.First().EventExp)</th>
<th style="width: 5%">
<button class="btn btn-sm btn-success btn-addrow" type="button">
<i class="fa fa-plus-square"></i>
</button>
</th>
</tr>
</thead>
<tbody>
#Html.Partial("AllDetailRows", Model)
</tbody>
</table>
</div>
</fieldset>
any idea?
thanks is advance

How refresh a view in MVC

I have _LayoutOnecs.html file and View Loads with in it renderbody and displays list of records in table. in one of table column i have a Delete icon on click of it goes to controller and deletes record from database once the record is deleted the view should be refreshed so i returned the action to controller which fetches all the records
public ActionResult GetAdvertisementDetails()
{
var advertisementList = new AdvertisementManager().GetAdvertisementDetails();
return View("AdvertisementDetails", advertisementList);
}
public ActionResult DeleteAdvertisementDetails(int id)
{
new AdvertisementManager().DeleteAdvertisementDetails(id);
return RedirectToAction("GetAdvertisementDetails", "Advertisement");
}
once Delete is done it is going to GetAdvertisementcontroller and return view but the Deleted record sits there in table if i Refresh the page by pressing F5 the record is removed from table.
How do i Refresh automatically when the record is deleted
View Code
<div class="col-md-12 main_table">
<div class="table-responsive">
<table class="table" id="hom_table">
<tr>
<th>Advertisement Name</th>
<th>Link</th>
<th>Start Date</th>
<th>End Date</th>
<th width="100">Action</th>
</tr>
#foreach (var advertisements in Model)
{
<tr>
<td> #advertisements.Description</td>
<td> #advertisements.ImageUrl</td>
<td> #advertisements.StartDate</td>
<td> #advertisements.EndDate</td>
<td>
<a onclick="EditadvertisementDetails(#advertisements.AdvertisementId)">
<i class=" pull_Advt_details tbl_edit_btn fa fa-edit Editbutton"></i>
</a>
<a id="Deladvertisement" onclick="Deleteadvertisement(#advertisements.AdvertisementId)" >
<i class="tbl_del_btn fa fa-trash"></i>
</a>
</td>
</tr>
}
</table>
</div>
<!-- Responsive main table Ends -->
</div>
Ajax calls stay on the same page. Your use of return RedirectToAction("GetAdvertisementDetails", "Advertisement"); in the controller method is ignored. Its also unnecessary to redirect since you can just remove the row from the table
Modify the html to (note remove the id attribute which is generating invalid html):
<a class="delete" data-id="#advertisements.AdvertisementId>
<i class="tbl_del_btn fa fa-trash"></i>
</a>
and use the following script to call the controller method and remove the row
var url = '#Url.Action("DeleteAdvertisementDetails", "Advertisement")';
$('.delete').click(function() {
var row = $(this).closest('tr');
$.post(url, { id: $(this).data('id') }, function(response) {
if(response) {
row.remove();
}
}).fail(function (response) {
// display error message?
});
});
and modify the controller to
[HttpPost]
public JsonResult DeleteAdvertisementDetails(int id)
{
new AdvertisementManager().DeleteAdvertisementDetails(id);
return Json(true);
}

Paging issue in ASP.Net Mvc Application

I am developing an MVC application in which I use a DropdownList to select "vendor". When I select a vendor from the dropdown then the view shows products related to the selected vendor.
I use paging to display multiple pages of particular vendor's products.
My issue is when I select a vendor from dropdown, at change event it displays products on all pages properly. If I select 2nd page it shows products from 2nd page. But next time if I select another vendor from dropdown, it shows 2nd page of selected vendor. But what I want is to display first page of selected vendor initially.
Controller code as below
public ActionResult Index(int? page ,int VendorId = 0)
{
var pageNumber = (page ?? 1);
var pagesize = 2;
if (VendorId == 0)
{
VendorId = Convert.ToInt32(Session["InventoryVendorId"]);
}
VendorService vendorService = new VendorService();
SelectList SelectList = new SelectList(vendorService.GetAll().OrderBy(t => t.Name), "Id", "Name", VendorId);
ViewData["list"] = SelectList;
int id = Convert.ToInt32(Session["loggedEmpId"]);
CommonService.SetEmployeeId(id);
if (VendorId != 0)
{
Session["InventoryVendorId"] = VendorId;
ProductService ProductService = new ProductService();
var productList = ProductService.GetProductInventory().Where(x=>x.VendorId == VendorId);
return View(productList.ToPagedList(pageNumber, pagesize));
}
else
{
return View();
}
}
code for view as below
#model PagedList.IPagedList<StockWatch.DTO.ProductDTO>
#using PagedList.Mvc;
#using System.Web.UI.WebControls
#{
ViewBag.Title = "Index";
int VendorId = Convert.ToInt32(Session["InventoryVendorId"]);
}
<link href="~/Content/PagedList.css" rel="stylesheet" />
<div class="row-fluid">
<div id="vendorDropdownDiv4" class="span12 " style="margin-left:0px;margin-top:10px;">
<div class="span6" >
<div class="span4" style="margin-left:1px;" >
<label >Vendor</label>
</div>
<div class="span6" >
#Html.DropDownList("VendorId", ViewData["list"] as SelectList, "-- Select vendor --", new { #id = "vendorIdforInventory", #name = "VendorId" })
</div>
</div>
<div class="span3" style="text-align:right">
#* <input class="btn btn-primary" type="submit" value="Load" id="create"/>*#
#*<input class="btn btn-default" value="Cancel" style="width:45px;" onclick="window.location.href='#Url.Action("index") '"/>*#
</div>
</div>
</div>
<div id="Newindexview"></div>
#if(Model != null)
{
</div>
<div class="span12" style="margin-left:0px;">
<table>
<thead>
<tr >
<th style="width:250px;" >Product Name
</th>
<th style="width:180px; text-align:left;" >Product Code
</th>
<th style="border-right: solid #e8eef4 thick; width: 0px; text-align:right;">Avg. Weight
</th>
#{
foreach (var location in ViewBag.loc)
{
<th style="width:10px;text-align:right;">#location.Name</th>
}
}
</tr>
</thead>
<tbody>
#foreach (var p in Model)
{
<tr>
<td style="width:250px;">
#p.Name
</td>
<td style="width:180px;text-align:left;">
#p.ProductCode
</td>
<td style="border-right: solid #e8eef4 thick; width: 15px; text-align:right">
#p.AvgWeight
</td>
#foreach (var location in ViewBag.loc)
{
flag = false;
if(p.Inventory != null)
{
foreach (var loc in p.Inventory)
{
if (location.Name == loc.LocationName)
{
<td style="width:10px; text-align:right;">#loc.Quantity</td>
flag = true;
}
}
}
if (flag == false)
{
<td style="width:10px; text-align:right;">0</td>
}
}
</tr>
}
</tbody>
</table>
</div>
<div class="span12" style="margin-left:0px;">
<div class="span6" style="margin-left:0px;">
#Html.PagedListPager(Model, page => Url.Action("Index", new {page ,searchContent=searchcontent}))
</div>
</div>
</div>
}
and jquery code as below
$("#vendorIdforInventory").change(function () {
var vendorid = $('#vendorIdforInventory').val();
$.ajax({
url: '#Url.Action("Index", "Inventory")',
data: {
VendorId: vendorid
},
type: "POST",
success: function (data) {
location.reload();
$('#modeldiv1').empty();
$('#vendorDropdownDiv4').hide();
$('#Newindexview').html("");
$('#Newindexview').html(data);
}
});
});
How to solve this paging issue?
You need to pass the currentFilter from your view back into your controller (which you have with VendorID), and set the page accordingly. Details are in the ASP.NET tutorial on paging at http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/sorting-filtering-and-paging-with-the-entity-framework-in-an-asp-net-mvc-application.
Look at how they've implemented filtering using the searchString and currentFilter variable, that's what will make sure that when a new string is entered (or selected from a drop down list in your case) that the paging responds accordingly.
Specifically, this is what I think you're missing in your code
if (searchString != null)
{
page = 1;
}
else
{
searchString = currentFilter;
}
...
int pageNumber = (page ?? 1);

Partial View with self updating

I'm learning ASP.NET MVC and I've encountered a problem in my practice project (MVC Music Store). I have made a partial view to search for an artist. I expect the partial view to take no arguments and work on its own.
Partial view in the right half part
I have a view specific model for the Artist Search Partial View. The model is as follows:
public class ArtistSearch
{
public string SearchString { get; set; }
public List<Artist> SearchResult { get; set; }
public ArtistSearch()
{
SearchResult=new List<Artist>();
}
}
Controller code is as follows:
public ActionResult Search(string query)
{
ArtistSearch asResult = new ArtistSearch();
if (query != null)
{
var temp = from a in db.Artists
where a.Name.Contains(query)
select a;
asResult.SearchResult = temp.ToList();
asResult.SearchString = query;
}
return PartialView(asResult);
}
The Partial View is as follows:
#model MvcMusicStore.Models.ArtistSearch
<div class="big-search-box">
<form action="#Url.Action("Search","Artist")" method="post" role="form">
<div class="input-group">
#Html.TextBox("query", #Model.SearchString, new { #class = "form-control nrb input-lg", placeholder = "Input your search query..." })
<div class="input-group-btn">
<input type="submit" name="Send" value="Search" class="btn btn-primary btn-iconed btn-lg" />
</div>
</div>
</form>
</div>
<div class="big-search-result-info clearfix">
<div class="pull-left">Showing results for <strong>#Model.SearchString</strong>.</div>
<div class="pull-right"><strong>#Model.SearchResult.Count</strong> artist(s) found.</div>
</div>
<table>
#foreach (var item in #Model.SearchResult)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
<a href="#item.Id" >
<img src=#item.PhotoURL alt=#item.Name style="width:100px;height:70px;">
</a>
</td>
</tr>
}
</table>
I wish to place this partial view anywhere on the site. Lets say i placed it(using RenderAction) on Artist/Index Controllers View page.
The simple functionality that I'm trying to achieve is that when i click on search it should self update the partial view with search results. Right now it is transferring me to Artist/Search page.
Thanks for the patience.
Try to use Ajax.BeginForm, below is an example:
Action
public ActionResult Search(string query)
{
ArtistSearch asResult = new ArtistSearch();
if (query != null)
{
var temp = from a in db.Artists
where a.Name.Contains(query)
select a;
asResult.SearchResult = temp.ToList();
asResult.SearchString = query;
}
return PartialView("MyParitalView",asResult);
}
View
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.js"></script>
#using (Ajax.BeginForm("Search", "Home", new AjaxOptions { UpdateTargetId = "result" }))
{
<div class="input-group">
#Html.TextBox("query", #Model.SearchString, new { #class = "form-control nrb input-lg", placeholder = "Input your search query..." })
<div class="input-group-btn">
<input type="submit" name="Send" value="Search" class="btn btn-primary btn-iconed btn-lg" />
</div>
</div>
}
<div id="result"></div>
Parital View : MyParitalView
#model MvcMusicStore.Models.ArtistSearch
<div class="big-search-result-info clearfix">
<div class="pull-left">Showing results for <strong>#Model.SearchString</strong>.</div>
<div class="pull-right"><strong>#Model.SearchResult.Count</strong> artist(s) found.</div>
</div>
<table>
#foreach (var item in #Model.SearchResult)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
<a href="#item.Id">
<img src=#item.PhotoURL alt=#item.Name style="width:100px;height:70px;">
</a>
</td>
</tr>
}
</table>

Resources