开发者

MVC; "System.Web.HttpException: A public action method 'Delete' was not found on controller 'SHP.Controllers.EmployeeController'."

开发者 https://www.devze.com 2023-02-14 18:28 出处:网络
I want to delete a row from my grid. I have found out that I cannot decorate my Delete method on my Controller with [HttpDelete] because it is not cross browser compatible, see http://forums.asp.net/t

I want to delete a row from my grid. I have found out that I cannot decorate my Delete method on my Controller with [HttpDelete] because it is not cross browser compatible, see http://forums.asp.net/t/1658625.aspx/1?The+DELETE+Http+works+in+FF+but+not+in+IE

I am displaying a grid using this EditorTemplate;

<tr>
    <td>
        <%-- Ajax Delete --%>
        <% if(Model.LeaveId > 0) { %>
        <%: Html.DeleteEmployeeOtherLeave("/Employee/Delete/" + Model.LeaveId.ToString(), Model)%>
        <%} %>
    </td>
    <td><%: Model.LeaveType %></td>
    <td><%: Model.MorningOnlyFlag %></td>
    <td><%: Model.AfternoonOnlyFlag %></td>
    <td><%: Model.DayAmount %></td>
    <td><%: String.Format("{0:ddd MMM d yyyy}", Model.Date)%></td>
</tr>

My HTML helper calls a javascript function;

function DeleteRow(href) {
    var flag = confirm('Are you sure you wish to delete this item?');
    if (flag == true) {
        $.ajax({
            url: href,
            type: 'POST',
            success: function (result) {
                $('#wholepage').html(result);
            }
        });
    }
    return false;

This function gets executed and the intention is to call the Delete method on my Controller;

 #region Absence (including sickness)
    [HttpGet]        
    [Authorize(Roles = "Administrator, AdminAccounts, ManagerAccounts")]
    public ActionResult EmployeeAbsence()
    {
        if ((SessionObjects.AbsenceStartDate > DateTime.MinValue) && (SessionObjects.AbsenceEndDate > DateTime.MinValue))
            if (SessionObjects.AbsenceSelectedEmployeeId == 0)
                return View(new AbsenceViewModel()
                {
                    AbsenceStartDate = SessionObjects.AbsenceStartDate,
                    AbsenceEndDate = SessionObjects.AbsenceEndDate
                });
            else
                return View(new AbsenceViewModel(
                    SessionObjects.AbsenceStartDate,
                    SessionObjects.AbsenceEndDate,
                    SessionObjects.AbsenceSelectedEmployeeId
                    ));

        return View();
    }

    [HttpPost]
    public ActionResult EmployeeAbsence(AbsenceViewModel _avm)
    {
        if (ModelState.IsValid)
        {
            SessionObjects.AbsenceStartDate = _avm.AbsenceStartDate;
            SessionObjects.AbsenceEndDate = _avm.AbsenceEndDate;
            if (_avm.SearchTextId > 0)
                SessionObjects.AbsenceSelectedEmployeeId = _avm.SearchTextId;
            return RedirectToAction("EmployeeAbsence");
        }
        return View(_avm);
    }

    [HttpPost]
    public ActionResult Delete(int id)
    {
        EmployeeOtherLeaf.Delete(id);
        return RedirectToAction("EmployeeAbsence");
    }
    #endregion

The Delete method does not get called.

I have been asked about the delete link which in my opinion works because I put a breakpoint in FireFox, but here it is defined in the HtmlHelper method.

public static MvcHtmlString DeleteEmployeeOtherLeave(this HtmlHelper html, string url, Leave _leave)
{
    string linkText = "Delete";
    return html.RouteLink(linkText, "Defau开发者_JAVA技巧lt",
        new { _employeeOtherLeaveId = _leave.LeaveId, action = "Delete" },
        new { onclick = "DeleteRow('" + url + "')" }   
        );
}


Why are you hardcoding urls like this:

<%: Html.DeleteEmployeeOtherLeave("/Employee/Delete/" + Model.LeaveId.ToString(), Model)%>

Always use url helpers when dealing with urls:

<%: Html.DeleteEmployeeOtherLeave(
    Url.Action("Delete", "Employee", new { id = Model.LeaveId }), 
    Model
)%>

Also how many times are you specifying this url? Wouldn't it be more straightforward:

public static MvcHtmlString DeleteEmployeeOtherLeave(this HtmlHelper<Leave> html)
{
    var leave = html.ViewData.Model;
    return html.RouteLink(
        "Delete", 
        "Default",
        new { _employeeOtherLeaveId = leave.LeaveId, action = "Delete" },
        new { onclick = "return DeleteRow(this);" }
    );
}

which would be called like this:

<%: Html.DeleteEmployeeOtherLeave() %>

(I would probably add the Link suffix to make this extension method a little more meaningful to what it actually does => generate a delete link)

and then:

function DeleteRow(a) {
    var flag = confirm('Are you sure you wish to delete this item?');
    if (flag == true) {
        $.ajax({
            url: a.href,
            type: 'POST',
            success: function (result) {
                $('#wholepage').html(result);
            }
        });
    }
    return false;
}

Also notice the return statement here: onclick = "return DeleteRow(this);". If you don't put it your AJAX call will never have the time to execute and you will simply be redirected to the Delete action which of course will throw a 404 exception because this action is not accessible through a GET request.

0

精彩评论

暂无评论...
验证码 换一张
取 消