Кнопка MVC 5 Ajax.BeginForm Submit вызывает текущую страницу вместо URL указанного контроллера и действия

#asp.net-mvc-5 #ajax.beginform

#asp.net-mvc-5 #ajax.beginform

Вопрос:

Я пытаюсь использовать Ajax.BeginForm, чтобы я мог передать значение флажка в действие моего контроллера.

Я использовал @Ajax.ActionLink, но я не могу получить значение недавно введенного флажка, поэтому я хочу использовать Ajax.BeginForm в будущем.

Начиная с @Ajax.ActionLink работает в представлении, я предполагаю, что Ajax работает должным образом, поэтому я могу это исключить.

Вот несколько вариантов, которые я пробовал. Когда я наводлю курсор на кнопки, они обе отображают URL моей веб-страницы вместо URL контроллера и действия. Когда я нажимаю на кнопки, страница в основном обновляется вместо вызова действия getCode в контроллере PublicOffers.

Любая помощь очень ценится! Спасибо!

Вариант 1

 <div>
    @using (Ajax.BeginForm("GetCode", "PublicOffers", null, new AjaxOptions()
    {
     UpdateTargetId = "detailsDiv",
     InsertionMode = InsertionMode.Replace,
     HttpMethod = "GET",
     OnBegin = "onStart",
     OnComplete = "onComplete",
     OnSuccess = "myCallback"
    }))
    {
     //bool checkedOption = false;
     //@Html.CheckBoxFor(x => checkedOption, new { Name = "OptIn" })

     @Html.CheckBoxFor(model => model.OptIn);
     @Html.HiddenFor(model => model.Id);

     <input type="submit" value="Get Code" class="button btn-primary" />
     }
</div>
  

Вариант 2

 <div>    
   @using (Ajax.BeginForm(new AjaxOptions() 
   { HttpMethod = "GET", 
     Url = "PublicOffers/GetCode", 
     InsertionMode = InsertionMode.Replace, 
     UpdateTargetId = "detailsDiv", 
     OnBegin = "onStart", 
     OnComplete = "onComplete", 
     OnSuccess = "myCallback" 
   }))
   {
       //bool checkedOption = false;
       //@Html.CheckBoxFor(x => checkedOption, new { Name = "OptIn" })
       @Html.CheckBoxFor(model => model.OptIn)
       //@Html.HiddenFor(model => model.Id, new { Name = "OfferId" })
       @Html.HiddenFor(model => model.Id);
       @Html.AntiForgeryToken()

       <input type="submit" value="Submit" />
    }
</div>
  

Комментарии:

1. Можете ли вы предоставить код контроллера для варианта 1?

2. Я добавил это в свой ответ, чтобы люди могли видеть, как передать значение флажка контроллеру.

Ответ №1:

Это не совсем ответ, но он может помочь.

Сначала убедитесь, что у вас есть это, я использую NuGet для его установки, Microsoft.jQuery.Ненавязчивый.Ajax

Затем убедитесь, что она отправляется на страницу либо через bundle scripts, либо через ссылку на скрипт в cshtml

Сначала простая модель…

 namespace AjaxTest.Models
{
    public class AjaxTestModel
    {
        public bool OptIn { get; set; }

    }
}
  

Далее немного cshtml…

 @model AjaxTest.Models.AjaxTestModel
@{ ViewBag.Title = "AjaxTest1";}
<h2>AjaxTest1</h2>
@using (Ajax.BeginForm("AjaxTest1", "Home", null,
    new AjaxOptions
    {
        HttpMethod = "POST",
        OnSuccess = "OnSuccess(xhr)",
        OnFailure = "OnFailure(xhr, status)"
    },
    new { id = "myform" }))
{
    @Html.CheckBoxFor(model => model.OptIn);
    <span id="lbl_message"></span>
    <br />
    <button id="btn_submit" type="submit" class="">Submit</button>
}
@section scripts{
    <script>
        $(document).ready(function () {
            console.log("ready to rock and roll....");
        });
        function OnBegin() {
            console.log("OnBegin");
        }
        function OnSuccess(xhr) {
            console.log("OnComplete");
            $("#lbl_message").text("Ok:"   xhr.responseJSON.param2);
        }
        function OnFailure(xhr, status) {
            console.log("OnFailure");
            $("#lbl_message").text("Error:"   xhr.responseJSON.param2);
        }
    </script>
}
  

Волшебство заключается в контроллере, обратите внимание, что я возвращаю объект Json, а не представление.

 public class HomeController : Controller
{
    public ActionResult AjaxTest1()
    {
        AjaxTestModel model = new AjaxTestModel();
        return View();
    }
    [HttpPost]
    public ActionResult AjaxTest1(AjaxTestModel model)
    {
        if (model.OptIn)
        {
            dynamic errorMessage = new { param1 = "param1", param2 = "You opted in." };
            HttpContext.Response.StatusCode = (int)HttpStatusCode.OK;
            return Json(errorMessage, JsonRequestBehavior.AllowGet);
        }
        else
        {
            dynamic errorMessage = new { param1 = "param1", param2 = "You opted out." };
            HttpContext.Response.StatusCode = (int)HttpStatusCode.NotFound;
            return Json(errorMessage, JsonRequestBehavior.AllowGet);
        }
    }
}
  

Обратите внимание, HttpContext.Response.StatusCode будет определять, какой обратный вызов Ajax активирован, возвращать HttpStatusCode.Ок, и onSuccess будет вызван, верните HttpStatusCode.Не найден или почти любой другой код ошибки, и будет вызван сбой.

Комментарии:

1. Спасибо за помощь! У меня получилось, но я не использовал ваш метод. Пожалуйста, смотрите мой ответ ниже. Я понятия не имею, почему это работает.

2. Если это помогло, вы можете щелкнуть значок «помогло», повысить мою репутацию :))

Ответ №2:

Я заставил это работать, добавив метод beginform.BeginForm для начала. Это почти так, как будто первый экземпляр вызывает второй метод Ajax.BeginForm. Поскольку в первом методе нет кнопки или чего-либо еще, на странице ничего не отображается.

ПРИМЕЧАНИЕ: Я изменил свой Get на Post, чтобы атрибут [ValidateAntiForgeryToken] работал для действия контроллера. Я читал, что это не сработало бы с Get.

 <div>
  @using (Ajax.BeginForm("GetCode", "PublicOffers", new { offerId = Model.Id }, new AjaxOptions()
  {
    //Nothing here, but for some reason without this code the Ajax.BeginForm below won't work                                        
  }))
  {
    //Nothing here, but for some reason without this code the Ajax.BeginForm below won't work    
  }
</div>

<div>
  @using (Ajax.BeginForm("GetCode", "PublicOffers", new { offerId = Model.Id },
    new AjaxOptions { OnBegin = "onStart", UpdateTargetId = "detailsDiv",
    InsertionMode = InsertionMode.Replace, HttpMethod = "Post",
    OnComplete = "onComplete",
    OnSuccess = "myCallback"},
    new { @style = "display:inline-block" }))
    {
      @Html.AntiForgeryToken()

      <div class="form-horizontal">
        <div class="form-group">
          @Html.CheckBoxFor(model => model.OptIn, new { Name = "optIn"})
        </div>
      </div>
       <input type="submit" class="button btn-primary" value="Get Code" id="get-code button" />
    }
</div>
  

Вот мое действие контроллера.

 [HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> GetCode(Guid offerId, bool optIn = false)
{
  //Code here 

  return PartialView("_OfferCode");
}