PartialView не возвращает связанные свойства модели - PullRequest
1 голос
/ 12 июня 2019

У меня есть контроллер, который я звоню через JQuery AJAX. Он берет данные на моей странице и возвращает частичное представление. Цель этого представления - предварительно заполнить некоторые поля ввода данными, которые я извлекаю из источника данных.

Проблема в том, что, когда частичное представление отображается в браузере, входные значения поля формы не заполняются значениями, которые я добавил в модель представления.

Я могу поставить точку останова на строке Return и увидеть, что vm правильно заполнен моими свойствами, как я хотел бы.

Но когда я просматриваю ответ на вкладке сети в Chrome Developer Tools, значения остаются пустыми.

У кого-нибудь есть идеи, почему?

Контроллер

[HttpPost]
        public async Task<IActionResult> ViewEditRaceOption(RaceViewModel race)
        {
            var vm = race;
            var option = race.RaceOptionData.FirstOrDefault(o => o.Number == race.EditOption);
            vm.OptionAffiliatedDiscountValue = option.AffiliatedDiscountValue;
            vm.OptionColour = option.OptionColour;
            vm.OptionEmbedMapURL = option.EmbedMapURL;
            vm.OptionEntryPremium = option.Premium;
            vm.OptionEntryPrice= option.AffiliatedDiscountValue;
            vm.OptionMaxEntries= option.MaxEntries;
            vm.OptionName= option.Name;
            vm.OptionRaceDistance = option.RaceDistance;
            vm.OptionStartTime = option.StartTime;
            vm.OptionCertificateFileName = option.CourseMeasurementCertificateFileName;

            return PartialView("OptionModal", vm);
        }

Главный вид (содержит Ajax JS), усеченный

@using TechsportiseOnline.Helpers
@model TechsportiseOnline.ViewModels.RaceViewModel

@{
    ViewData["Title"] = "Race";
}
<script>
    $(function () {
        $("#racedatepicker").datepicker({
            dateFormat: "d MM yy",
            changeMonth: true,
            changeYear: true
        });
    });
</script>
@if (Model.FormAction == "Create")
{
    <h2>Create a new race</h2>
}
else
{
    <h2>@Model.RaceData.Name | <span class="text-muted">Edit Race</span></h2>
    <h4>@Model.RaceData.RaceDate.ToString("dd MMMM yyyy")</h4>
}


<form asp-action="@Model.FormAction" enctype="multipart/form-data" id="race">
    <input type="hidden" name="FormAction" value="@Model.FormAction" />
    <input id="DeleteOption" name="DeleteOption" type="hidden" value="0" />
    <input id="EditOption" name="EditOption" type="hidden" value="0" />





    <div asp-validation-summary="ModelOnly" class="text-danger"></div>
    <div class="modal fade bd-example-modal-lg" tabindex="-1" role="dialog" aria-labelledby="myLargeModalLabel" aria-hidden="true" id="optionsmodal">
        <div class="modal-dialog modal-lg">

            <div class="modal-content">
                <div class="modal-header">

                    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                        <span aria-hidden="true">&times;</span>
                    </button>
                    <h2 class="modal-title">Race Option</h2>
                    <input type="hidden" name="NewOption" value="false" id="NewOption" />
                </div>
                <div class="modal-body">
                    @{Html.RenderPartial("_StatusMessage", Model.Message);}

                    <div id="optionmodal">
                        @{Html.RenderPartial("OptionModal", Model);}
                    </div>











                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-default cancelmodal">Cancel</button>
                    <button type="button" class="btn btn-primary" id="addoption">Add</button>
                </div>
            </div>
        </div>
    </div>










    <div class="container">
        <div class="row">
            <div class="col-md-6">
                <div class="panel panel-default">
                    <div class="panel-heading">Race Details</div>
                    <div class="panel-body">
                        <div class="row">
                            <div class="col-md-12">
                                <div class="form-group">
                                    <label asp-for="RaceData.Name" class="control-label"></label>
                                    <br /><small class="text-muted">The name or title of your race</small>
                                    <input asp-for="RaceData.Name" class="form-control" />
                                    <span asp-validation-for="RaceData.Name" class="text-danger"></span>
                                </div>
                            </div>
                        </div>

                        <div class="row">
                            <div class="col-md-12">
                                <div class="form-group">
                                    <label asp-for="RaceData.ContactName" class="control-label"></label>
                                    <br /><small class="text-muted">The name of the Race Director whom people should contact with queries</small>
                                    <input asp-for="RaceData.ContactName" class="form-control" />
                                    <span asp-validation-for="RaceData.ContactName" class="text-danger"></span>
                                </div>
                            </div>
                        </div>

                        <div class="row">
                            <div class="col-md-6">
                                <div class="form-group">
                                    <label asp-for="RaceData.ContactEmail" class="control-label"></label>
                                    <br /><small class="text-muted">The email address of the Race Director whom people should contact with queries</small>
                                    <input asp-for="RaceData.ContactEmail" class="form-control" />
                                    <span asp-validation-for="RaceData.ContactEmail" class="text-danger"></span>
                                </div>
                            </div>
                            <div class="col-md-6">
                                <div class="form-group">
                                    <label asp-for="RaceData.ContactNumber" class="control-label"></label>
                                    <br /><small class="text-muted">The phone number of the Race Director whom people should contact with queries</small>
                                    <input asp-for="RaceData.ContactNumber" class="form-control" />
                                    <span asp-validation-for="RaceData.ContactNumber" class="text-danger"></span>
                                </div>
                            </div>
                        </div>



                        <div class="row">
                            <div class="col-md-6">
                                <div class="form-group">
                                    <label asp-for="RaceData.RaceDate" class="control-label"></label>
                                    <div class="input-group">
                                        <span class="input-group-addon"><i class="icon-calendar"></i> </span>
                                        <input name="RaceData.RaceDate" value="@Model.RaceData.RaceDate.ToString("dd MMMM yyyy")" type="text" class="form-control" id="racedatepicker" autocomplete="off">
                                    </div>
                                    <span asp-validation-for="RaceData.RaceDate" class="text-danger"></span>
                                </div>
                            </div>

                        </div>



                        <div class="form-group">
                            <label asp-for="RaceData.Description" class="control-label"></label>
                            <br /><small class="text-muted">As much description as you want to add for your race to give your participants as much as they need to know</small>

                            <textarea asp-for="RaceData.Description" class="form-control" rows="10" id="description">@Model.RaceData.Description</textarea>
                            <span asp-validation-for="RaceData.Description" class="text-danger"></span>
                        </div>




                    </div>
                </div>


                <div class="panel panel-default">
                    <div class="panel-heading">Race Options</div>
                    <div class="panel-body">
                        <div id="container">
                            Create your different Race Options here, if you want to have more than one distance/race in the same event. You must have at least 1 Race Option.
                            <div id="dvRaceOptionsResults">
                                @{Html.RenderPartial("RaceOptions", Model);}
                            </div>
                            <button type="button" class="btn btn-primary" data-toggle="modal" data-target=".bd-example-modal-lg">Add Race Option</button>
                        </div>
                    </div>
                </div>


            </div>
           TRUNCATED HERE


        <div class="form-group">
            @if (Model.FormAction == "Create")
            {
                <input type="submit" value="Create" class="btn btn-primary" />
            }
            else
            {
                <input type="submit" value="Save" class="btn btn-primary" />

            }

        </div>
        <div>
            <a asp-action="Index">Back to List</a>
        </div>

</form>








<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/1000hz-bootstrap-validator/0.11.9/validator.min.js"></script>

@section Scripts {
    @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
    <script type="text/javascript">
        $(document).on('click', '.cancelmodal', function () {
            console.log("cancel modal")
            var premiumrace = document.getElementById("RaceData_Premium").value
            document.getElementById("OptionName").value = ""
            document.getElementById("OptionRaceDistance").value = ""
            document.getElementById("OptionMaxEntries").value = 0
            document.getElementById("OptionStartTime").value = "19:00"
            document.getElementById("OptionEmbedMapURL").value = ""
            document.getElementById("OptionColour").value = "White"
            document.getElementById("OptionEmbedMapURL").value = ""
            if (premiumrace == true) {
                document.getElementById("OptionEntryPremium").value = false
                document.getElementById("OptionEntryPrice").value = "0"
                document.getElementById("OptionAffiliatedDiscountValue").value = "2.00"
            }

            $("#optionsmodal").modal("hide")
        });
    </script>


    <script type="text/javascript">
        $(document).on('click', '.editmodal', function () {

        var optionnumber = $(this).attr('number');
        document.getElementById("EditOption").value = optionnumber;

        var form = document.getElementById('race');
        var formData = new FormData(form);

         $.ajax({
            url: '@Url.Action("ViewEditRaceOption", "Races")',
            type: 'POST',
            data: formData,
            dataType: 'html',
            processData: false,
            contentType: false,
            success: function(response) {
            if (response) {  // check if data is defined
                $("#optionmodal").html(response);
                console.log(response);
                $("#optionsmodal").modal("show");
                }
            }
        });            

        document.getElementById("EditOption").value = 0;

    });
    </script>





    <script type="text/javascript">
    $(document).on('click', '.editoption', function () {
    var optionnumber = $(this).attr('number');
    document.getElementById("EditOption").value = optionnumber;

    var form = document.getElementById('race');
    var formData = new FormData(form);

        $.ajax({
            url: '@Url.Action("EditRaceOption", "Races")',
            type: 'POST',
            data: formData,
            dataType: 'html',
            processData: false,
            contentType: false,
            success: function(response) {
            if (response) {  // check if data is defined
                $("#dvRaceOptionsResults").html(response);
                }
            }
        });

    document.getElementById("EditOption").value = 0;
    });
    </script>
    <script type="text/javascript">
    $(document).on('click', '.removeoption', function () {
    var optionnumber = $(this).attr('number');
    document.getElementById("DeleteOption").value = optionnumber;


    $.ajax({
    url: '@Url.Action("RemoveRaceOption", "Races")',
    type: 'POST',
    data: $("#race").serialize(),
    dataType: 'html',
    success: function(response) {
    if (response) {  // check if data is defined
    $("#dvRaceOptionsResults").html(response);
    }
    }
    });
    document.getElementById("DeleteOption").value = 0;
    });
    </script>

    <script type="text/javascript">

    $("#addoption").click(function () {
    document.getElementById("NewOption").value = "true";

    var form = document.getElementById('race');
    var formData = new FormData(form);

    $.ajax({
    url: '@Url.Action("AddRaceOption", "Races")',
    type: 'POST',
    data: formData,
    dataType: 'html',
    processData: false,
    contentType: false,
    success: function(response) {
    if (response) {  // check if data is defined
    $("#optionsmodal").modal("hide");
    $("#dvRaceOptionsResults").html(response);
    document.getElementById("OptionName").value = null;
    document.getElementById("OptionRaceDistance").value = "";
    }
    }
    });
    document.getElementById("NewOption").value = "false";
    });
    </script>

    <script type="text/javascript">

        tinymce.init({
            selector: 'textarea',
            height: 400,
            menubar: false,
            plugins: [
                'advlist autolink lists link image charmap print preview anchor textcolor',
                'searchreplace visualblocks code fullscreen',
                'insertdatetime media table contextmenu paste code help'
            ],
            toolbar: 'preview | formatselect | bold italic underline strikethrough forecolor | alignleft aligncenter alignright alignjustify | bullist numlist | image link media | removeformat ',
            content_css: [
                '//fonts.googleapis.com/css?family=Lato:300,300i,400,400i',
                '//www.tinymce.com/css/codepen.min.css']
        });

        // Prevent Bootstrap dialog from blocking focusin
        $(document).on('focusin', function (e) {
            if ($(e.target).closest(".mce-window").length) {
                e.stopImmediatePropagation();
            }
        });

    </script>

    <script type="text/javascript" src="~/js/autocomplete/jquery.easy-autocomplete.min.js"></script>
    <link rel="stylesheet" href="~/js/autocomplete/easy-autocomplete.min.css">
    <script type="text/javascript">
        var options = {

            url: "../../resources/countries.json",

            getValue: "name",

            list: {
                match: {
                    enabled: true
                }
            },

            theme: "square"
        };

        $("#countries").easyAutocomplete(options);
    </script>

    <script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCZMX9gUpf7jFKwPe6r6dtqmrv-EnnXsU4&libraries=places&callback=initAutocomplete"
            async defer></script>

    <script type="text/javascript">
        var placeSearch, autocomplete;
        var componentForm = {
            street_number: 'short_name',
            route: 'long_name',
            administrative_area_level_1: 'short_name',
            administrative_area_level_2: 'short_name',
            postal_town: 'short_name',
            country: 'long_name',
            postal_code: 'short_name'
        };

        function initAutocomplete() {
            // Create the autocomplete object, restricting the search to geographical
            // location types.
            autocomplete = new google.maps.places.Autocomplete(
            /** type {!HTMLInputElement} */(document.getElementById('autocomplete')),
                { types: ['geocode'] });

            // When the user selects an address from the dropdown, populate the address
            // fields in the form.
            autocomplete.addListener('place_changed', fillInAddress);
        }

        function fillInAddress() {
            // Get the place details from the autocomplete object.
            var place = autocomplete.getPlace();

            for (var component in componentForm) {
                document.getElementById(component).value = '';
                document.getElementById(component).disabled = false;
            }

            // Get each component of the address from the place details
            // and fill the corresponding field on the form.
            for (var i = 0; i < place.address_components.length; i++) {
                var addressType = place.address_components[i].types[0];
                if (componentForm[addressType]) {
                    var val = place.address_components[i][componentForm[addressType]];
                    document.getElementById(addressType).value = val;
                }
            }
        }

        // Bias the autocomplete object to the user's geographical location,
        // as supplied by the browser's 'navigator.geolocation' object.
        function geolocate() {
            if (navigator.geolocation) {
                navigator.geolocation.getCurrentPosition(function (position) {
                    var geolocation = {
                        lat: position.coords.latitude,
                        lng: position.coords.longitude
                    };
                    var circle = new google.maps.Circle({
                        center: geolocation,
                        radius: position.coords.accuracy
                    });
                    autocomplete.setBounds(circle.getBounds());
                });
            }
        }



    </script>
}




Частичное представление

@model TechsportiseOnline.ViewModels.RaceViewModel

<div class="row">
    <div class="col-md-4">
        <div class="form-group">
            <label value="OptionName" class="control-label">Option Name</label>
            <br /><small class="text-muted">The name of this Race Option</small>
            <input asp-for="OptionName" name = "OptionName" placeholder="Your 10k" type="text" class="form-control" aria-label="Name">
            <span asp-validation-for="OptionName" class="text-danger"></span>
        </div>
    </div>
    <div class="col-md-4">
        <div class="form-group">
            <label name="OptionRaceDistance" value="Race Distance" class="control-label">Distance</label>
            <br /><small class="text-muted">Choose a race distance, used for Age Grading </small>

            <select asp-for="OptionRaceDistance" required class="form-control">
                <option value="" selected>--select--</option>
                <option value="M1">1 mile</option>
                <option value="KM5">5 km</option>
                <option value="KM6">6 km</option>
                <option value="M4">4 miles</option>
                <option value="KM8">8 km</option>
                <option value="M5">5 miles</option>
                <option value="KM10">10 km</option>
                <option value="KM12">12 km</option>
                <option value="KM15">15 km</option>
                <option value="M10">10 miles</option>
                <option value="KM20">20 km</option>
                <option value="Half">Half Marathon</option>
                <option value="KM25">25 km</option>
                <option value="KM30">30 km</option>
                <option value="Marathon">Marathon</option>
                <option value="KM50">50 km</option>
                <option value="M50">50 miles</option>
                <option value="KM100">100 km</option>
                <option value="KM150">150 km</option>
                <option value="M100">100 miles</option>
                <option value="KM200">200 km</option>
                <option value="Other">Other</option>
            </select><br />
            <span asp-validation-for="OptionRaceDistance" class="text-danger"></span>
        </div>
    </div>
    <div class="col-md-4">
        <div class="form-group">
            <label name="OptionMaxEntries" value="Maximum Entries" class="control-label">Maximum Entries</label>
            <br /><small class="text-muted">The maximum capacity of the race</small>


            <input asp-for="OptionMaxEntries" class="form-control" type="number" />
            <span asp-validation-for="OptionMaxEntries" class="text-danger"></span>
        </div>
    </div>
</div>

<div class="row">
    <div class="col-md-6">
        <div class="form-group">
            <label name="OptionStartTime" value="Start Time" class="control-label">Race Start Time</label>
            <br /><small class="text-muted">Start time in HH:MM</small>
            <input asp-for="OptionStartTime" value="19:00" asp-format="{0:hh:mm}" class="form-control" type="time" />
            <span asp-validation-for="OptionStartTime" class="text-danger"></span>
        </div>
    </div>


    <div class="col-md-6">
        <div class="form-group">
            <label class="control-label">Colour</label>
            <br /><small class="text-muted">Choose the colour for this option. </small>
            <select asp-for="OptionColour" class="form-control">
                <option value="White" selected>White</option>
                <option value="Red">Red</option>
                <option value="Blue">Blue</option>
                <option value="Yellow">Yellow</option>
                <option value="Green">Green</option>
                <option value="Silver">Silver</option>
                <option value="Orange">Orange</option>
            </select><br />
        </div>
    </div>
</div>


<div class="row">
    <div class="col-md-6">
        <div class="form-group">
            <label class="control-label">Course Measurement Certificate</label>
            <br /><small class="text-muted">PDF file of certificate for this race option</small>
            <input asp-for="OptionCourseMeasurementCertificateFile" type="file" class="form-control" />
            <span asp-validation-for="OptionCourseMeasurementCertificateFile" class="text-danger"></span>
        </div>
    </div>
    <div class="col-md-6">
        <div class="form-group">
            <label class="control-label">Course Map URL</label>
            <br /><small class="text-muted">Provide a URL to a Garmin, Strava or other course mapping tool</small>
            <input asp-for="OptionEmbedMapURL" class="form-control" />
            <span asp-validation-for="OptionEmbedMapURL" class="text-danger"></span>
        </div>
    </div>
</div>




@if (Model.RaceData.CanBePremium)
                    {
<div class="row">
    <div class="col-md-4">
        <div class="form-group">
            <div class="checkbox">
                <label>
                    <input asp-for="OptionEntryPremium" /> Premium Race Option
                    <br /><small class="text-muted">This is a premium race option and will cost @Model.BaseCurrency.Symbol@Model.BaseFee.ToString("0.00") per race entry</small>
                </label>
            </div>
        </div>
    </div>
    <div class="col-md-4">
        <div class="form-group">
            <label value="OptionEntryPrice" class="control-label">Entry Price</label>
            <br /><small class="text-muted">The price of the normal race entry</small>
            <input asp-for="OptionEntryPrice" type="number" class="form-control" aria-label="Amount" placeholder="10.00" asp-format="{0:0.00}" >
            <span asp-validation-for="OptionEntryPrice" class="text-danger"></span>
        </div>
    </div>

    <div class="col-md-4">
        <div class="form-group">
            <label class="control-label">Affiliation Discount</label>
            <br /><small class="text-muted">Value of discount for affiliation</small>
            <input asp-for="OptionAffiliatedDiscountValue" type="number" class="form-control" aria-label="Amount" value="2.00" asp-format="{0:0.00}" >
            <span asp-validation-for="OptionAffiliatedDiscountValue" class="text-danger"></span>
        </div>
    </div>
</div>

                    }




enter image description here

...