Reputation: 5150
I have two identical methods.
My [HttpGet] method returns a list of all data for my KPI's Model.
My [HttpPost] version needs to return a list of data within a date range for my KPI's model.
[HttpGet]
public ActionResult ViewDepartment (int id = 0)
{
// populate the IPACS_kpiHistory with all available data in the department
var kpi = model.IPACS_Department.IPACS_Functions.SelectMany(m => m.IPACS_Processes).SelectMany(m => m.IPACS_Procedures).SelectMany(m => m.IPACS_KPIS);
foreach (var item in kpi)
{
model.IPACS_KPIS.Add(item);
}
return View(model);
}
[HttpPost]
public ActionResult ViewDepartment (int id, System.DateTime startDate, system.DateTime endDate)
{
// populate the IPACS_kpiHistory with all available data in the department
var kpi = model.IPACS_Department.IPACS_Functions.SelectMany(m => m.IPACS_Processes).SelectMany(m => m.IPACS_Procedures).SelectMany(m => m.IPACS_KPIS);
foreach (var item in kpi)
{
model.IPACS_KPIS.Add(item);
}
return View(model);
}
On the view page I need to display a list of every single KPI (found in IPACS_KPIS) I then sum the data for each KPI (found in IPACS_kpiHistory).
Here is my view page section:
@foreach (var item in @Model.IPACS_KPIS)
{
<tr class="gradeX">
<td>
@item.name
</td>
<td>
@item.IPACS_kpiHistory.Select(m => m.startAmount).Sum()
</td>
<td>
@item.IPACS_kpiHistory.Select(m => m.completedAmount).Sum()
</td>
<td>
@item.IPACS_kpiHistory.Select(m => m.endAmount).Sum()
</td>
</tr>
}
How do I correctly filter out the data for the [HttpPost] and find values between the startDate
and endDate
?
The only way I can think of doing it is adding 2 properties to my model a startDate
and an endDate
and using those on the razor page but trying to see if it is possible to do all that work in the controller and keep the razor page clean.
Criteria:
Must display every single KPI (even if it has no data (currently works like this) )
Must filter out items not between the daterange
in the [HttpPost]
method.
Upvotes: 0
Views: 420
Reputation: 1963
As stated by another poster you should use Get for both of these controller methods. It's not a big deal, but it is the normal convention. Then you would have one method that is a get and takes id, start date, end date.
If you use just get or both get and post, you can still solve this problem without any logic being on the view (since it shouldn't be there).
Add start date and end date to the model. Then set those properties or variables in the controller. Then create a method on the model Model.GetFilteredKPIS() this method returns all the KPIS that are between start date and end date in the model.
Then the razor will be clean:
@foreach (var item in @Model.GetFilteredKPIS())
{
<tr class="gradeX">
<td>
@item.name
</td>
<td>
@item.IPACS_kpiHistory.Select(m => m.startAmount).Sum()
</td>
<td>
@item.IPACS_kpiHistory.Select(m => m.completedAmount).Sum()
</td>
<td>
@item.IPACS_kpiHistory.Select(m => m.endAmount).Sum()
</td>
</tr>
}
Upvotes: 1
Reputation: 21308
Your approach is wrong. POST should only be used for posting data back to server. "GET" method should be used when the form processing is "idempotent", and in those cases only. As a simplification, we might say that "GET" is basically for just getting (retrieving) data whereas "POST" may involve anything, like storing or updating data, or ordering a product, or sending E-mail.
Why not do the following (this approach will give a generic functionality that takes care of all type of filtering/searching etc):
Create a custom filter:
public class SearchAttribute : ActionFilterAttribute
{
#region Public Methods and Operators
/// <summary>
/// Overrides method OnActionExecuting, fires before every controller action is executed. Method retrives list search parameters from current url and saves them in
/// SearchParams base controller dictionary.
/// </summary>
/// <param name="filterContext">
/// The filter Context.
/// </param>
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
foreach (string key in filterContext.HttpContext.Request.QueryString.AllKeys)
{
if ((key != null) && key.StartsWith("f_"))
{
filterContext.Controller.ViewData[key] =
filterContext.HttpContext.Request.QueryString[key].ToLower();
}
}
}
#endregion
}
So anything that comes via Url with "f_" will be treated as a filter parameter.
Decorate your controller with the FilterAttribute you've created above:
[Search]
public ActionResult Index()
{
var qs = this.ControllerContext.RequestContext.HttpContext.Request.QueryString
....
}
"qs" holds now your querystring that you can parse and depending on filters there you return the correct list.
Upvotes: 1
Reputation: 21766
To sum the values within a certain range, just add a Where clause:
@item.IPACS_kpiHistory.Where(m => m.date >= Model.MinDate && m.date <= Model.MaxDate)
.Sum(m => m.startAmount)
Upvotes: 1
Reputation: 6866
You could change your foreach loop in you post method to something like this
foreach (var item in kpi)
{
if (startdate <= item.date && item.date <= enddate)
{
model.IPACS_KPIS.Add(item);
}
}
You will have to change it to use the relevant properties of your objects.
Upvotes: 0