Отправьте значения из вида бритвы в действие контроллера, которое принимает значения методом HTTP Post - PullRequest
3 голосов
/ 30 января 2020

У меня есть представление в одном из моих контроллеров, у которого есть список элементов. Когда пользователь щелкает по каждому элементу, браузер должен перейти на страницу с подробной информацией об этом элементе.

Контроллер для Details принимает значения через метод post и имеет в качестве входных данных сложный объект ввода.

Здесь это пример метода перехода на страницу сведений с использованием метода GET для отправки значений:

function openDetailsPage(commodityID, commodityName) {

     dateFrom = convertNumbers2English('@(((FilterViewModel)ViewBag.ViewModel).dateValue_1)');
    dateTo = convertNumbers2English('@(((FilterViewModel)ViewBag.ViewModel).dateValue_2)');

    dateFrom = changeDateSeparator(dateFrom);
    dateTo = changeDateSeparator(dateTo);

    if (dateTo == null || dateTo == undefined)
        dateTo = "0";

    if (dateFrom == null || dateFrom == undefined)
        dateFrom = "0";
    @{
        string reportTypes = "0";
        if (((FilterViewModel)ViewBag.ViewModel).purchaseReportTypes != null)
        {
            reportTypes = String.Join(",", ((FilterViewModel)ViewBag.ViewModel).purchaseReportTypes);
        }
    }
    alert('@reportTypes');
    var url = '@Url.Action("ReportDetailed","BuyReport",new {
        commodityType =(((FilterViewModel)ViewBag.ViewModel).commodityType),
        commodityName="dummyCommodityName",
        department=((FilterViewModel)ViewBag.ViewModel).department,
        repository=((FilterViewModel)ViewBag.ViewModel).repository,
        commodity ="dummyCommodityID",
        purchaseReportTypes=reportTypes,
        dateValue_1="dummyDate1",
        dateValue_2="dummyDate2"
    })';
    alert(url);

    @*var url = '@Url.Action("ReportDetailed","BuyReport",
    new RouteValueDictionary
    {
        {"commodityType",((FilterViewModel)ViewBag.ViewModel).commodityType},
        {"commodityName","dummyCommodityName" },
        {"department",((FilterViewModel)ViewBag.ViewModel).department },
        {"repository",((FilterViewModel)ViewBag.ViewModel).repository },
        {"commodity","dummyCommodityID"},
        {"purchaseReportTypes",((FilterViewModel)ViewBag.ViewModel).purchaseReportTypes },
        {"dateValue_1",((FilterViewModel)ViewBag.ViewModel).dateValue_1 },
        { "dateValue_2",((FilterViewModel)ViewBag.ViewModel).dateValue_2 }

    })';*@
    url = url.replace("dummyCommodityID", commodityID);
    url = url.replace("dummyCommodityName", commodityName);
    url = url.replace("dummyDate1", dateFrom);
    url = url.replace("dummyDate2", dateTo);
    alert(url);
    openLink(url);
}

У меня есть некоторые трудности с этим типом маршрутизации для значений:

  1. Входной объект сложен, поэтому маршрут будет таким сложным. Например, /BuyReport/ReportDetailed?commodityType=0&commodityName=dummyCommodityName&department=1&repository=2&commodity=dummyCommodityID&dateValue_1=dummyDate1&dateValue_2=dummyDate2 или /BuyReport/ReportDetailed/0/itemName/1/2/1/123/
  2. Любые специальные символы в параметрах получения, такие как /, будут нарушать маршрутизацию
  3. Я не могу передавать такие вещи, как массивы, поэтому я должен преобразовать их перед отправкой

Итак, я ищу метод для отправки параметров, используя метод 'Post', например, что кнопка отправки формы делает с нижеследующими ограничениями:

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

Я хочу знать, есть ли какие-либо способы реализации Post параметров в соответствии с моими требованиями? Мне было бы все равно, если это будет смесь C#, JS и jQuery.

Подробнее:

Вот пример строки в моя страница списка, которая вызывает функцию openDetailsPage js:

<a onclick="openDetailsPage(@item.CommodityId,'@Html.DisplayFor(modelItem => item.CommodityName)')">
    <div class="ios-content-box px-4 py-1 mb-3 ios-hover-box">
        <div class="row font-12 my-2 ios-divider-line">
            <div class="col-6 f-w-600 color-orange text-right">@Html.DisplayFor(modelItem => item.CommodityName)</div>
            <div class="col-6 text-left"> <i class="fas fa-chevron-left  fa-fw  color-orange "></i></div>
        </div>
        <div class="row font-12 my-2 ios-divider-line">
            <div class="col-6 text-gray-600 text-right">type</div>
            <div class="col-6 text-gray-600 text-left">@Html.DisplayFor(modelItem => item.TypesName)</div>
        </div>
        <div class="row font-12 my-2 ios-divider-line">
            <div class="col-6 text-gray-600 text-right">Code</div>
            <div class="col-6 text-gray-600 text-left">@Html.DisplayFor(modelItem => item.CommodityCode)</div>
        </div>
        <div class="row font-12 my-2 ios-divider-line">
            <div class="col-6 text-gray-600 text-right">Barcode</div>
            <div class="col-6 text-gray-600 text-left">@Html.DisplayFor(modelItem => item.CommodityBarcode)</div>
        </div>
        <div class="row font-12 my-2 ios-divider-line">
            <div class="col-6 text-gray-600 text-right">Unit Price</div>
            <div class="col-6 text-gray-600 text-left">@Html.DisplayFor(modelItem => item.UnitPrice)</div>
        </div>
        <div class="row font-12 my-2 ios-divider-line">
            <div class="col-6 text-gray-600 text-right">Total Price</div>
            <div class="col-6 text-gray-600 text-left">@Html.DisplayFor(modelItem => item.SumPrice)</div>
        </div>
    </div>
</a>

В настоящее время мой контроллер выглядит следующим образом:

[Route("BuyReport/ReportDetailed/{commodityType}/{commodityName}/{department}/{repository}/{commodity}/{purchaseReportTypes}/{dateValue_1}/{dateValue_2}")]

public async Task<ActionResult> ReportDetailed(
    string commodityType, 
    string commodityName,
    string department,
    string repository,
    string commodity,
    string purchaseReportTypes,
    string dateValue_1,
    string dateValue_2
    )
{


}

Но я хочу изменить его на что-то вроде этого:

[HttpPost]
public async Task<ActionResult> ReportDetailed(DetailedViewModel detailedviewmodel){

    string commodity = detailedviewmodel.commodity;
    string commoditytype = detailedviewmodel.commoditytype;
    string department = detailedviewmodel.department;
    string purchasereporttypes = detailedviewmodel.purchasereporttypes;
    string repository = detailedviewmodel.repository;
    string startdate = detailedviewmodel.datevalue_1;
    string enddate = detailedviewmodel.datevalue_2;
    string commdoityname = detailedviewmodel.commodityname;

}

Где DetailedViewModel определяется следующим образом:

public class DetailedViewModel
{
    public string commodityType { get; set; }
    public string commodityName { get; set; }
    public string department { get; set; }
    public string repository { get; set; }
    public string commodity { get; set; }
    public string[] purchaseReportTypes { get; set; }

    public string dateValue_1 { get; set; }//start date
    public string dateValue_2 { get; set; }//end date

}

Ответы [ 3 ]

6 голосов
/ 06 февраля 2020

Это неправильный способ достичь вашей цели . Ваш код выглядит уязвимым и для эксплуататоров. Не используйте решения, которые нарушают нормальное поведение веб-приложений.

Вместо этого отправьте параметры в соответствующий метод контроллера, а затем выполните внутреннее перенаправление с передачей модели (сторона контроллера). Если ваши данные хранятся в базе данных, просто отправьте CommodityId и найдите детали на стороне контроллера, а не отправляйте все детали как form (HTTPPOST). Таким образом, у вас есть хорошо разработанный проект без нежелательных сбоев, возникающих из-за нарушения поведения, и ваш код выглядит простым и понятным, как вы хотите.

3 голосов
/ 02 февраля 2020

Одним из простых простых решений является публикация через Ajax:

Давайте представим это как ваш контроллер :

    [HttpGet]
    public ActionResult ReportDetailed()
    {
        return View();
    }



    [HttpPost]
    public JsonResult ReportDetailed(DetailedViewModel detailedviewmodel)
    {
        var status = "error";
        var message = "";
        try
        {
            string commodity = detailedviewmodel.commodity;
            string commoditytype = detailedviewmodel.commodityType;
            string department = detailedviewmodel.department;
            List<string> purchasereporttypes = detailedviewmodel.purchaseReportTypes;
            string repository = detailedviewmodel.repository;
            string startdate = detailedviewmodel.dateValue_2;
            string enddate = detailedviewmodel.dateValue_1;
            string commdoityname = detailedviewmodel.commodityName;


            // your code here ...


            status = "success";                
            return Json(new { status, detailedviewmodel } , JsonRequestBehavior.AllowGet);
        }
        catch (Exception ex)
        {
            message = ex.Message;
            return Json(new { status, message }, JsonRequestBehavior.AllowGet);
        }            
    }

Предположим, вы определили DetailedViewModel внутри папки Models:

public class DetailedViewModel
{
    public string commodityType { get; set; }
    public string commodityName { get; set; }
    public string department { get; set; }
    public string repository { get; set; }
    public string commodity { get; set; }
    public List<string> purchaseReportTypes { get; set; }
    public string dateValue_1 { get; set; }//start date
    public string dateValue_2 { get; set; }//end date
}

В вашем Представлении я скопирую для вас целые Html и Javascript, просто возьмите их и настройте под свои нужды:

@model Your_Proj_Namespace.Models.DetailedViewModel

@{
    ViewBag.Title = "ReportDetailed";
}

<h2>ReportDetailed</h2>

@using (Html.BeginForm())
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>DetailedViewModel</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.commodityType, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.commodityType, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.commodityType, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.commodityName, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.commodityName, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.commodityName, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.department, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.department, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.department, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            <label>purchaseReportTypes: 3 inputs for example</label>
            <div class="col-md-10">
                <input type="text" name="purchaseReportTypes[0]" class="form-control inputPurchaseReportTypes " value="" />
                <input type="text" name="purchaseReportTypes[1]" class="form-control inputPurchaseReportTypes " value="" />
                <input type="text" name="purchaseReportTypes[2]" class="form-control inputPurchaseReportTypes " value="" />
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.repository, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.repository, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.repository, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.commodity, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.commodity, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.commodity, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.dateValue_1, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.dateValue_1, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.dateValue_1, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            @Html.LabelFor(model => model.dateValue_2, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-10">
                @Html.EditorFor(model => model.dateValue_2, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.dateValue_2, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" id="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}




@section scripts{
    <script>
        $('#submit').click(function (e) {
            e.preventDefault();
            alert('form submitted');


            var list = [];
            $('.inputPurchaseReportTypes').each( function (key, value) {
                list.push($(this).val());
            });



            const DATA = {
                commodityType: $('#commodityType').val(),
                commodityName: $('#commodityName').val(),
                department: $('#department').val(),
                repository: $('#repository').val(),
                commodity: $('#commodity').val(),
                purchaseReportTypes: list,
                dateValue_1: $('#dateValue_1').val(),
                dateValue_2: $('#dateValue_2').val(),
            };


            console.log(DATA);


            $.ajax({
                url: '/YourControllerName/ReportDetailed',
                type: "POST",
                contentType: "application/json",
                dataType: "json",
                data: JSON.stringify(DATA),

                success: function (result) {
                    alert('success');
                    console.log(result);
                    // your code here
                }
            });
        });



    </script>
}

Если вы предпочитаете не использовать Ajax, прокомментируйте приведенный выше код javascript (весь код внутри <script>), чтобы опубликовать форму напрямую. Я построил и отладил приведенный выше код. Не стесняйтесь проверить это.

Надеюсь, что это помогло.

Наконец, вам могут пригодиться следующие ссылки:

2 голосов
/ 04 февраля 2020

Я согласен с решением @A. Наджар

еще одна заметка

Используйте HttpGet , если вы хотите, чтобы пользователь поделился URL и показывал те же данные , что и он увидеть его для другого пользователя,

, если нет? используйте HttpPost с одним параметром объекта , потому что, возможно, есть параметры Nullable, по которым пользователь не будет искать, поэтому URL будет выглядеть так

BuyReport/ReportDetailed/dummyCommodityName/null/null/null/dummyCommodityID/null/2/0

или не используйте этот пользовательский маршрут [Route("BuyReport/ReportDetailed/{commodityType}/{commodityName}/{department}/{repository}/{commodity}/{purchaseReportTypes}/{dateValue_1}/{dateValue_2}")], чтобы он мог использовать строку запроса и передавать только ключи => значения, которые он хочет

...