The PageSize field indicates that information should be displayed on one page, about eight objects, but the page displays everything that is in the database.
private readonly IObjectRepository _objectRepository;
private readonly IWebHostEnvironment hostingEnvironment;
public int PageSize = 8;
public HomeController(IObjectRepository objectRepository, IWebHostEnvironment hostingEnvironment)
{
_objectRepository = objectRepository;
this.hostingEnvironment = hostingEnvironment;
}
public ViewResult Index(int objectPage)
{
var model = _objectRepository.GetAllObjects();
model.OrderBy(o => o.Id)
.Skip((objectPage - 1) * PageSize)
.Take(PageSize);
return View(model);
}
Skip and Take return a new IEnumerable as a result, instead of modifying the existing one in place. So, you should replace this line:
model.OrderBy(o => o.Id)
.Skip((objectPage - 1) * PageSize)
.Take(PageSize);
with:
model=model.OrderBy(o => o.Id)
.Skip((objectPage - 1) * PageSize)
.Take(PageSize);
This way, you assign the new query value to the baseQuery and then when you enumerate it, it will return the expected entities.
Thanks everyone! I found another solution with Methanit, thanks him a lot.
1 - Changed my PageViewModel
public class PageViewModel
{
public int PageNumber { get; set; }
public int TotalPages { get; set; }
public PageViewModel(int count, int pageNumber, int pageSize)
{
PageNumber = pageNumber;
TotalPages = (int)Math.Ceiling(count / (double)pageSize);
}
public bool HasPreviousPage
{
get
{
return (PageNumber > 1);
}
}
public bool HasNextPage
{
get
{
return (PageNumber < TotalPages);
}
}
}
2 - Changed method Index in Controller:
public IActionResult Index(int page = 1)
{
int pageSize = 6;
var model = _objectRepository.GetAllObjects();
var count = model.Count();
var items = model.Skip((page - 1) * pageSize).Take(pageSize).ToList();
PageViewModel pageViewModel = new PageViewModel(count, page, pageSize);
IndexViewModel viewModel = new IndexViewModel
{
PageViewModel = pageViewModel,
Objects = items
};
return View(viewModel);
}
3 - The application is working correctly.
Thanks all a lot!
Related
Generate headers like so:
public void ClearDataGrid()
{
this.xDataGrid.ItemsSource = null;
//// [Grid Headr 초기 세팅]
//this.xDataGrid.Columns.Clear();
//this.m_Model.MeasureData.Clear();
this.xDataGrid.Columns.Clear();
//// [Wave header 생성]
//Column cNo = GridUtil.Instance.SetColumn(ColumnTypes.Text, "No", "No", new ColumnWidth() { Value = 75 });
//this.xDataGrid.Columns.Add(cNo);
DevExpress.XamarinForms.DataGrid.TextColumn cNo = GridUtil.Instance.SetColumn(ColumnTypes.Text, "No", "No", 75) as DevExpress.XamarinForms.DataGrid.TextColumn;
this.xDataGrid.Columns.Add(cNo);
// [파장값 입력]
for (int i = 0; i < this.m_Model.WaveLength.Count; i++)
{
string strID = string.Empty;
if ((DisplayDataType)Enum.Parse(typeof(DisplayDataType), this.m_Model.DisplayDataUnitType.ToString()) == DisplayDataType.ABS)
{
strID = string.Format("ABS[{0}]", i);
DevExpress.XamarinForms.DataGrid.NumberColumn Col = GridUtil.Instance.SetColumn(
ColumnTypes.Numeric,
strID,
string.Format("A[{0}]", this.m_Model.WaveLength[i]),
150) as DevExpress.XamarinForms.DataGrid.NumberColumn;
this.xDataGrid.Columns.Add(Col);
}
else
{
strID = string.Format("Trans[{0}]", i);
DevExpress.XamarinForms.DataGrid.NumberColumn Col = GridUtil.Instance.SetColumn(
ColumnTypes.Numeric,
strID,
string.Format("T[{0}]", this.m_Model.WaveLength[i]),
150) as DevExpress.XamarinForms.DataGrid.NumberColumn;
this.xDataGrid.Columns.Add(Col);
}
}
DevExpress.XamarinForms.DataGrid.TextColumn cCell = GridUtil.Instance.SetColumn(ColumnTypes.Text, "Cell", "Cell", 75) as DevExpress.XamarinForms.DataGrid.TextColumn;
DevExpress.XamarinForms.DataGrid.DateColumn cDateTime
= GridUtil.Instance.SetColumn(ColumnTypes.Date, "Date", "Date", 150) as DevExpress.XamarinForms.DataGrid.DateColumn;
this.xDataGrid.Columns.Add(cCell);
this.xDataGrid.Columns.Add(cDateTime);
this.xDataGrid.ItemsSource = this.m_Model.MeasureData;
}
When a button is clicked, temporary data is created and added to the bound model.
private async void BtnMeasureClick(object sender, EventArgs e)
{
PhotometricMeasureData data = new PhotometricMeasureData();
++nIndex;
data.No = nIndex.ToString();
data.Cell = string.Format("C[{0}]", nIndex);
data.DateTime = DateTime.Now;
for (int i = 0; i < this.m_Model.WaveLength.Count; i++)
{
data.OriginABS.Add(new Random().Next(-10, 10));
data.OriginTrans.Add(new Random().Next(-10, 10));
data.ABS.Add(data.OriginABS[i] * this.m_Model.Factor);
data.Trans.Add(data.OriginTrans[i] * this.m_Model.Factor);
}
this.m_Model.MeasureData.Add(data);
//this.xDataGrid.Columns[0].Pinned = PinnedPositions.Left;
//this.xDataGrid.ScrollToLastRowByIndex(this.m_Model.MeasureData.Count-1);
}
binding model
public BindingList<PhotometricMeasureData> MeasureData
{
set; get;
} = new BindingList<PhotometricMeasureData>();
public class PhotometricMeasureData : INotifyPropertyChanged
{
//List<float> m_lstABS = new List<float>();
//List<float> m_lstTrans = new List<float>();
public string No { get; set; }
public string Cell { get; set; }
public DateTime DateTime { get; set; }
public BindingList<float> ABS
{
get; set;
} = new BindingList<float>();
public BindingList<float> Trans
{
get; set;
} = new BindingList<float>();
public BindingList<float> OriginABS
{
get; set;
} = new BindingList<float>();
public BindingList<float> OriginTrans
{
get; set;
} = new BindingList<float>();
public void UpdateABSByFactor(float factor)
{
//this.ABS.Clear();
for (int i = 0; i < this.ABS.Count; i++)
{
this.ABS[i] = this.OriginABS[i] * factor;
OnPropertyChanged(string.Format("ABS[{0}]", i));
}
}
public void UpdateTransByFactor(float factor)
{
//this.Trans.Clear();
for (int i = 0; i < this.Trans.Count; i++)
{
this.Trans[i] = this.OriginTrans[i] * factor;
OnPropertyChanged(string.Format("Trans[{0}]", i));
}
}
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
In the current bound model, No and Cell DateTime are binding fine.
But the data created by BindingList is not being bound.
When creating a column in the header, the field name was created and inserted like string.Format("ABS[{0}]", i).
And I tried to bind the data accessed by the index of the ABS list of the binding model.
But it doesn't work as well as I thought.
What am I doing wrong?
enter image description here
enter image description here
Given a list of strings, I'd like to create a list of the following object
class LineInfo
{
public string line { get; set; }
public bool isSearchMatch { get; set; }
public int searchMatchNumber { get; set; }
}
Where I'd like searchMatchNumber to have 1 for the 1st match, 2 for the 2nd, etc. Otherwise it can be zero
I set this up like so
IEnumerable<string> allLines; //pulled in from somewhere
IEnumerable<LineInfo> logInfoLines = allLines.Select((l, i) => new LineInfo
{
line = l,
isSearchMatch = l.IndexOf(search, StringComparison.OrdinalIgnoreCase) >= 0
});
How can I set searchMatchNumber?
LINQ queries should not cause side effects like this. If you'd add an OrderBy you'd get a different result. I wouldn't use LINQ for this, you could provide a method:
class LineInfo
{
public string line { get; set; }
public bool isSearchMatch { get; set; }
public int searchMatchNumber { get; set; }
public static IEnumerable<LineInfo> GetSearchResult(IEnumerable<string> allLines, string search)
{
int matchCounter = 0;
var lineInfoList = new List<LineInfo>();
foreach (string line in allLines)
{
bool isMatch = line.IndexOf(search, StringComparison.OrdinalIgnoreCase) >= 0;
var li = new LineInfo
{
line = line,
isSearchMatch = isMatch,
searchMatchNumber = isMatch ? ++matchCounter : -1 // or whatever
};
lineInfoList.Add(li);
}
return lineInfoList;
}
}
I have 5 records coming from a simple select stored procedure.
ID Name
1 RecordOne
2 RecordTwo
3 RecordThree
4 RecordFour
5. RecordFive
Requirement is to display one record at a time example:
Record One
Previous Next
Two Action links or buttons with Previous and Next text.
If user clicks Next user will see
RecordTwo
and so on,same for previous case.
My model
namespace MVCLearning.Models
{
public class VMNews
{
public List<Student> StudentDetails { get; set; }
}
public class Student
{
public int ID { get; set; }
public string Name { get; set; }
}
}
Action
public ActionResult Index()
{
VMNews objnews = new VMNews();
objnews.StudentDetails = db.Database.SqlQuery<Student>("usp_studentdetails").ToList();
return View(objnews);
}
View
<div>
#foreach (var item in Model.SD.Take(1))
{
<h3>#item.Name</h3>
<h3>#item.Age</h3>
}
#Html.ActionLink("Next", "index", new { Model.SD[0].ID})
#Html.ActionLink("Previous", "index", new { Model.SD[0].ID })
The way I have written the view is totally wrong am not getting how and what to write on the action and what to write on the View.
What will be one of the way to achieve this.
Change you method to
public ActionResult Index(int? index)
{
int max = 5; // modify based on the actual number of records
int currentIndex = index.GetValueOrDefault();
if (currentIndex == 0)
{
ViewBag.NextIndex = 1;
}
else if (currentIndex >= max)
{
currentIndex = max;
ViewBag.PreviousIndex = currentIndex - 1;
}
else
{
ViewBag.PreviousIndex = currentIndex - 1;
ViewBag.NextIndex = currentIndex + 1;
}
VMNews objnews = new VMNews();
Student model = db.Database.SqlQuery<Student>("usp_studentdetails")
.Skip(currentIndex).Take(1).FirstOrDefault();
return View(model);
}
Note that the query has been modified to return only one Student since that is all that you require in the view. Also I have asssumed if a user enters a value greater than the number of records it will return the last record (you may in fact want to throw an error?)
The view now needs to be
#model Student
<h3>#Model.Name</h3>
<h3>#Model.Age</h3>
#if (ViewBag.PreviousIndex != null)
{
#Html.ActionLink("Previous", "Index", new { index = ViewBag.PreviousIndex })
}
#if (ViewBag.NextIndex != null)
{
#Html.ActionLink("Next", "Index", new { index = ViewBag.NextIndex })
}
I have the following code, I can figure why its invalid argument:
AuditDAL ad = new AuditDAL();
var agencies = ad.SearchAgencies("Ak001", "");
string col = param.sColumns.Split(',')[param.iSortCol_0];
string orderby = col + " " + param.sSortDir_0;
// The best overloaded method match for 'AMS.Helper.PaginatedList.PaginatedList(System.Linq.IQueryable, int, int)' has some invalid arguments C:\NexGen\AMS\DEV\Source\AMS\Controllers\AuditController.cs
var qry = new PaginatedList<AuditAgency>(agencies, param.iDisplayStart, param.iDisplayLength);
PaginatedList Code:
namespace AMS.Helper
{
public class PaginatedList<T> : List<T> {
public int PageIndex { get; private set; }
public int PageSize { get; private set; }
public int TotalCount { get; private set; }
public int TotalPages { get; private set; }
public PaginatedList(IQueryable<T> source, int pageIndex, int pageSize) {
PageIndex = pageIndex;
PageSize = pageSize;
TotalCount = source.Count();
TotalPages = (int) Math.Ceiling(TotalCount / (double)PageSize);
this.AddRange(source.Skip(PageIndex * PageSize).Take(PageSize));
}
public bool HasPreviousPage {
get {
return (PageIndex > 0);
}
}
public bool HasNextPage {
get {
return (PageIndex+1 < TotalPages);
}
}
}
}
Search Agencies Code:
public IEnumerable<AuditAgency> SearchAgencies(string ori, string name)
{
List<AuditAgency> agencies = new List<AuditAgency>();
using (var conn = new SqlConnection(_connectionString))
{
var com = new SqlCommand();
com.Connection = conn;
com.CommandType = CommandType.StoredProcedure;
string term = "Ori";
if (!String.IsNullOrEmpty(ori))
{
term = "Ori";
com.Parameters.Add(new SqlParameter
{
ParameterName = "#ORI",
Value = ori
});
}
if (!String.IsNullOrEmpty(name))
{
term = "legal_name";
com.Parameters.Add(new SqlParameter
{
ParameterName = "#Name",
Value = name
});
}
com.CommandText = "Audit_Get_Agency_List";
var adapt = new SqlDataAdapter();
adapt.SelectCommand = com;
var dataset = new DataSet();
adapt.Fill(dataset);
agencies = (from c in dataset.Tables[0].AsEnumerable()
select new AuditAgency()
{
Agency_ID = Convert.ToInt32(c["Agency_Id"]),
Agency_Name = c["Agency_Name"].ToString(),
Agency_Ori = c["ORI"].ToString(),
COPSAuditNumber = c["COPSAuditNumber"].ToString(),
OIGAuditNumber = c["OIGAuditNumber"].ToString()
}).ToList<AuditAgency>();
return agencies;
}
}
The error should tell you where to start.
If you fire up the debugger, I think you'll find agencies is an IEnumberable, but not an IQueryable
correct it by changing the return type of SearchAgencies from IQueryable to IEnumerable
or alternatively, you can change the type of the PaginatedList to accept IEnumberables instead of IQueryables. this may be safer as IQueryable inherits from IEnumerable
(see
http://msdn.microsoft.com/en-us/library/system.linq.iqueryable.aspx or
Differences between IQueryable, List, IEnumerator?
for the difference between the two)
Hi I am quite new on MVC and I am trying to create a simple conversion from Fahrenheit to Celsius along with its unit testing. Sorry in advance for putting all the code here.
This is my controller code:
public string Convert(double value,string option)
{
string d;
if(option=="1") {
d = " To Celcius"+FahrenheitToCelsius(value).ToString();
}
else {
d = " To Fahrenheit" + CelsiusToFahrenheit(value).ToString();
}
return "ConvertTo" + d;
}
public static double CelsiusToFahrenheit(double temperatureCelsius)
{
double celsius = temperatureCelsius;
return (celsius * 9 / 5) + 32;
}
public static double FahrenheitToCelsius (double temperatureFahrenheit)
{
double fahrenheit = temperatureFahrenheit;
return (fahrenheit - 32) * 5 / 9;
}
This is my View Page
protected void btnConvert(object sender, EventArgs e)
{
if (DropDownList1.SelectedValue=="1"){
double temp = TemperatureConverterController.FahrenheitToCelsius(double.Parse(TextBox1.Text));
Literal1.Text = temp.ToString();
}
else{
double temp = TemperatureConverterController.CelsiusToFahrenheit(double.Parse(TextBox1.Text));
Literal1.Text = temp.ToString();
Literal1.Text = temp.ToString();
}
}
When i do this unit testing i got an error:
[TestMethod]
public void ConvertReturnsAViewResultWhenInputDataIsValid()
{
//Arrange
var controller = new TemperatureConverterController();
//Act
double x = 80;
double y = 25;
var result = controller.Convert(x, "1") as ViewResult;
// here i get this error under ViewResult //
//Assert
Assert.IsInstanceOfType(result, typeof(ViewResult));
}
[TestMethod]
public void ConvertAsksForAViewTemplateNamedConvert()
{
//Arrange
var controller = new TemperatureConverterController();
String expectedViewTemplate = "Convert";
//Act
double x = 80;
double y = 25;
var result = controller.Convert(x, "1") as ViewResult;
////Assert
Assert.AreEqual<String>(expectedViewTemplate, result.ViewName);
}
Error is:
Error Cannot convert type 'string' to 'System.Web.Mvc.ViewResult' via a reference conversion, boxing conversion, unboxing conversion, wrapping conversion, or null type conversion.
the problem is here
var result = controller.Convert(x, "1") as ViewResult;
your Convert method is returning string and you are casting it as ViewResult
Your convert method should looks like
public ActionResult Convert()
{
//Make a Model class and pass it to View
//...
return View(model_class_object);
}
Alternatively you can make controller like this
public ActionResult Convert()
{
ViewData["tempvalue"]=Convert(x, "1");
//Make a Model class and pass it to View
//...
return View();
}
and on your View you can just print it
#ViewData["tempvalue"].ToString()
In MVC the controller code should return an "ActionResult" object containing the model.
If the data you want to pass to view is simply a string use:
public ActionResult Convert()
{
//...
return View("your result here...");
}
You can refer to data returned by controller using the "Model" property in Views or Tests.
Let's go backwards for a minute here.
Controller
public class ConvertController : Controller
{
public ActionResult Convert(MyConvertViewModel vm)
{
if (vm == null) { return View("convert", new MyConvertViewModel { ShowResult = false }); }
if (vm.Option == 1)
{
vm.Result = FahrenheitToCelsius(vm.Input);
vm.OptionName = "Fahrenheit To Celsius";
}
else
{
vm.Result = CelsiusToFahrenheit(vm.Input);
vm.OptionName = "Celsius to Fahrenheit";
}
vm.ShowResult = true;
//not needed, just for an example
ViewData.Add("glosrob-example", "A value goes here!");
return View("convert", vm);
}
private static double CelsiusToFahrenheit(double temperatureCelsius)
{
double celsius = temperatureCelsius;
return (celsius * 9 / 5) + 32;
}
private static double FahrenheitToCelsius(double temperatureFahrenheit)
{
double fahrenheit = temperatureFahrenheit;
return (fahrenheit - 32)*5/9;
}
}
public class MyConvertViewModel
{
public double Result { get; set; }
public int Option { get; set; }
public double Input { get; set; }
public string OptionName { get; set; }
public bool ShowResult { get; set; }
}
View
#model MvcApplication1.Controllers.MyConvertViewModel
#{
ViewBag.Title = "Convert";
}
<h2>Convert</h2>
#using (Html.BeginForm("convert", "convert", FormMethod.Post))
{
<div>
Let's convert some temperatures!
</div>
<div>
#Html.LabelFor(x => x.Input, "Temp. To Convert")
#Html.TextBoxFor(x => x.Input)
</div>
<div>
#Html.LabelFor(x => x.Option, "Convert to ")
#Html.DropDownListFor(x => x.Option, new List<SelectListItem>
{
new SelectListItem {Text = "Celsius", Value = "1"},
new SelectListItem {Text = "Fahrenheit", Value = "2"}
})
</div>
<div>
<button type="submit">Convert It!</button>
</div>
}
#if (Model.ShowResult)
{
<p>#Model.OptionName : #Model.Input = #Model.Result</p>
}
disclaimer: there is a lot of shortcuts there, it is only included to give you an idea of what you should have.
So the view will post back data the user chooses, to the controller action Convert
The controller in turn will return a ViewResult object, and it will be rendered using the data captured in the view model MyConvertViewModel
Now we want to test this.
So here are some of the more important properties that it seems like you need to hook into
[TestMethod]
public void Not_A_Real_Test_But_Stuff_You_Will_Want_To_Use()
{
//arrange
var c = new ConvertController();
//act
var results = c.Convert(null) as ViewResult;
//now results is a ViewResult or null
var theViewModelProperty = results.Model as MyConvertViewModel;
var exampleResult = theViewModelProperty.Result;
var exampleInput = theViewModelProperty.Input;
//etc
//how about the view that was returned?
var theViewName = results.ViewName;
//or anything you put in the ViewData
var theViewData = results.ViewData["glosrob-example"];
Assert.Fail("This was not a real test!");
}
Hopefully this gives you an idea of how you can test for output from a controller method.
Edit: I'm not writing all your tests for you but as an e.g.
[TestMethod]
public void Convert_Should_Return_A_MyConvertViewModel()
{
//arrange
var c = new Controller();
//act
var result = c.Convert(null) as ViewResult;
//assert
Assert.IsNotNull(result);
Assert.IsInstanceOfType(result.ViewModel, typeof(MyConvertViewModel));
}
[TestMethod]
public void Convert_Should_Return_The_Correct_View()
{
//arrange
var c = new Controller();
//act
var result = c.Convert(null) as ViewResult;
//assert
Assert.IsNotNull(result);
Assert.AreEqual("convert", result.ViewName);
}