简体   繁体   中英

HttpGet HttpPost method deviation

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.

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)

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):

  • Use HttpGet without any params => would give you default list
  • Use HttpGet with params (filters) => would give you a filtered list

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.

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>
}

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM