. Net -Core Controller не привязывает дочерний сложный тип в модели - PullRequest
0 голосов
/ 23 апреля 2020

Это действие, которое я пытаюсь связать с моделью:

    [HttpPost]
    public JsonResult SaveNewBusiness(NewBusinessVm newBusiness)
    {

    }

Это модель:

    public class NewBusinessVm 
    {
       public NewBusinessVm()
       {

       }

    public int ID { get; set; }
    public string Name { get; set; }
    public ImageViewModel MainImage { get; set; }
    public string Description { get; set; }
    public List<SelectListItem> CategorySelections { get; set; }
    public int CategoryID { get; set; }
    public List<SelectListItem> LocationSelections { get; set; }
    public string LocationStr { get; set; }
    public List<int> FacilitiesIDs { get; set; }
    public string GoogleAddress { get; set; }
    public string FriendlyAddress { get; set; }
    public string GooglePlaceID { get; set; }
    public string Lat { get; set; }
    public string Long { get; set; }
    public int MinPrice { get; set; }
    public int MaxPrice { get; set; }
}

Проблемное свойство c, которое не будет связываться, MainImage:

  public class ImageViewModel
    {
        public bool IsParent { get; set; }
        public string FileName { get; set; }
        public List<ImageViewModel> ChildImages { get; set; }
        public int? ImageFamilyId { get; set; }
        public string ImageUrl { get; set; }
        public string Title { get; set; }
        public string Alt { get; set; }
        public string Width { get; set; }
        public string Height { get; set; }
        public string Sizes { get; set; }
        public bool IsThumbNail { get; set; }
        public int Bytes { get; set; }
        public DateTime CreateTime { get; set; }
    }

Я добавляю MainImage к данным. На стороне клиента я попробовал все эти 3 метода:

        //#1
        var data = $form.serializeArray();
        data[data.length] = { name: "MainImage", value: mainImageObj };
        console.log(data);
        AjaxModule.Ajax(url, data, options);

        //#2
        var dataJson = JSON.stringify(data);
        console.log(dataJson);
        AjaxModule.Ajax(url, dataJson, options);

        //#3
        var data2 = $form.serialize();
        data2 += "&MainImage=" + JSON.stringify(mainImageObj);
        console.log(data2);
        AjaxModule.Ajax(url, data2, options);

Первый объект option выглядит следующим образом: enter image description here

Второй параметр:

[{"name":"Name","value":"BusinessName example"},{"name":"CategoryID","value":"80"},{"name":"Description","value":""},{"name":"GooglePlaceID","value":"ChIJy9AOJGrKM5QR23I19T-HKD0"},{"name":"Long","value":""},{"name":"Lat","value":""},{"name":"GoogleAddress","value":"La Posta, Cordoba, Argentina"},{"name":"FriendlyAddress","value":"Río Primero,La Posta"},{"name":"__RequestVerificationToken","value":"CfDJ8E3zPSvylsxAsVq_mjBa9qQxnItdTOHxZje0mUebkKW5pH2K2ZUkB_Flg3XJsUQh_8hxmqGvUJo_hLuQIz6xOiFR1Y5HCDeGmGGKFSM2h1cHGfGkr7SBkIkZr4ImqCDRiaaRmy0x1taJyFmcqRpXMVSBnBN5pcjWkqqNhuGYL09KKD2xFJwk1Tbhcyb7d2YEPw"},{"name":"MainImage","value":{"IsParent":true,"ImageUrl":"https://res.cloudinary.com/dzpwse6vo/image/upload/v1587727444/Businesses/44637/noyc0lpgto9t2p1j15kx.jpg","FileName":"Businesses/44637/noyc0lpgto9t2p1j15kx","Width":720,"Height":960,"CreateTime":"2020-04-24T11:24:04Z","Bytes":50450,"ChildImages":[{"IsParent":false,"ImageUrl":"https://res.cloudinary.com/dzpwse6vo/image/upload/c_crop,g_auto,h_350,q_auto,w_1600/v1587727444/Businesses/44637/noyc0lpgto9t2p1j15kx.jpg","FileName":"Businesses/44637/noyc0lpgto9t2p1j15kx","Width":720,"Height":350,"CreateTime":"2020-04-24T11:24:04Z","Bytes":21629},{"IsParent":false,"ImageUrl":"https://res.cloudinary.com/dzpwse6vo/image/upload/c_scale,q_auto,w_0.8/v1587727444/Businesses/44637/noyc0lpgto9t2p1j15kx.jpg","FileName":"Businesses/44637/noyc0lpgto9t2p1j15kx","Width":576,"Height":768,"CreateTime":"2020-04-24T11:24:04Z","Bytes":38069},{"IsParent":false,"ImageUrl":"https://res.cloudinary.com/dzpwse6vo/image/upload/c_scale,q_auto,w_0.6/v1587727444/Businesses/44637/noyc0lpgto9t2p1j15kx.jpg","FileName":"Businesses/44637/noyc0lpgto9t2p1j15kx","Width":432,"Height":576,"CreateTime":"2020-04-24T11:24:04Z","Bytes":25138},{"IsParent":false,"ImageUrl":"https://res.cloudinary.com/dzpwse6vo/image/upload/c_scale,q_auto,w_0.4/v1587727444/Businesses/44637/noyc0lpgto9t2p1j15kx.jpg","FileName":"Businesses/44637/noyc0lpgto9t2p1j15kx","Width":288,"Height":384,"CreateTime":"2020-04-24T11:24:04Z","Bytes":14803},{"IsParent":false,"ImageUrl":"https://res.cloudinary.com/dzpwse6vo/image/upload/c_scale,q_auto,w_0.2/v1587727444/Businesses/44637/noyc0lpgto9t2p1j15kx.jpg","FileName":"Businesses/44637/noyc0lpgto9t2p1j15kx","Width":144,"Height":192,"CreateTime":"2020-04-24T11:24:04Z","Bytes":5285,"IsThumbnail":true}]}}]

Третий вариант:

Name=BusinessName%20example&CategoryID=80&Description=&GooglePlaceID=ChIJy9AOJGrKM5QR23I19T-HKD0&Long=&Lat=&GoogleAddress=La%20Posta%2C%20Cordoba%2C%20Argentina&FriendlyAddress=R%C3%ADo%20Primero%2CLa%20Posta&__RequestVerificationToken=CfDJ8E3zPSvylsxAsVq_mjBa9qQxnItdTOHxZje0mUebkKW5pH2K2ZUkB_Flg3XJsUQh_8hxmqGvUJo_hLuQIz6xOiFR1Y5HCDeGmGGKFSM2h1cHGfGkr7SBkIkZr4ImqCDRiaaRmy0x1taJyFmcqRpXMVSBnBN5pcjWkqqNhuGYL09KKD2xFJwk1Tbhcyb7d2YEPw&MainImage={"IsParent":true,"ImageUrl":"https://res.cloudinary.com/dzpwse6vo/image/upload/v1587727444/Businesses/44637/noyc0lpgto9t2p1j15kx.jpg","FileName":"Businesses/44637/noyc0lpgto9t2p1j15kx","Width":720,"Height":960,"CreateTime":"2020-04-24T11:24:04Z","Bytes":50450,"ChildImages":[{"IsParent":false,"ImageUrl":"https://res.cloudinary.com/dzpwse6vo/image/upload/c_crop,g_auto,h_350,q_auto,w_1600/v1587727444/Businesses/44637/noyc0lpgto9t2p1j15kx.jpg","FileName":"Businesses/44637/noyc0lpgto9t2p1j15kx","Width":720,"Height":350,"CreateTime":"2020-04-24T11:24:04Z","Bytes":21629},{"IsParent":false,"ImageUrl":"https://res.cloudinary.com/dzpwse6vo/image/upload/c_scale,q_auto,w_0.8/v1587727444/Businesses/44637/noyc0lpgto9t2p1j15kx.jpg","FileName":"Businesses/44637/noyc0lpgto9t2p1j15kx","Width":576,"Height":768,"CreateTime":"2020-04-24T11:24:04Z","Bytes":38069},{"IsParent":false,"ImageUrl":"https://res.cloudinary.com/dzpwse6vo/image/upload/c_scale,q_auto,w_0.6/v1587727444/Businesses/44637/noyc0lpgto9t2p1j15kx.jpg","FileName":"Businesses/44637/noyc0lpgto9t2p1j15kx","Width":432,"Height":576,"CreateTime":"2020-04-24T11:24:04Z","Bytes":25138},{"IsParent":false,"ImageUrl":"https://res.cloudinary.com/dzpwse6vo/image/upload/c_scale,q_auto,w_0.4/v1587727444/Businesses/44637/noyc0lpgto9t2p1j15kx.jpg","FileName":"Businesses/44637/noyc0lpgto9t2p1j15kx","Width":288,"Height":384,"CreateTime":"2020-04-24T11:24:04Z","Bytes":14803},{"IsParent":false,"ImageUrl":"https://res.cloudinary.com/dzpwse6vo/image/upload/c_scale,q_auto,w_0.2/v1587727444/Businesses/44637/noyc0lpgto9t2p1j15kx.jpg","FileName":"Businesses/44637/noyc0lpgto9t2p1j15kx","Width":144,"Height":192,"CreateTime":"2020-04-24T11:24:04Z","Bytes":5285,"IsThumbnail":true}]}

Я пытался изменить подпись на
public JsonResult SaveNewBusiness([FromBody]NewBusinessVm newBusiness)

, а также на:
public JsonResult SaveNewBusiness([FromForm]NewBusinessVm newBusiness)

Все свойства связываются, как и ожидалось, за исключением этого. Любая помощь, это возможно?

Ответы [ 3 ]

0 голосов
/ 23 апреля 2020

Вы смешиваете и сопоставляете вещи здесь. Форма будет отправлена ​​как x-www-form-urlencoded, что в основном является просто парой ключ-значение. Установка объекта JSON в качестве значения одной из этих пар не приведет к десериализации этого JSON в объект при отправке таким способом, потому что это неизвестно или не указано, что это JSON; это просто строка, как и любая другая строка. Кроме того, весь объект здесь не будет привязан, так или иначе, потому что FromBody требует что-то вроде application/json, а не x-www-form-urlencoded. Для последнего вам понадобится FromForm.

Если вы хотите принять JSON, то вам нужно будет использовать AJAX для отправки сообщения (так как форма HTML не имеет возможность сделать это), и вам нужно будет отправить его в кодировке JSON, не используя скрытые входные данные с JSON -подобными строками в качестве значений.

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

0 голосов
/ 24 апреля 2020

Обычно, когда я публикую форму без сложного объекта, я делаю это так:

var data = $form.serialize();
AjaxModule.Ajax(url, data, options);

Но из-за сложного объекта мне пришлось манипулировать, чтобы сформировать входные данные для чистого javascript объект вроде так:

    //#1 form elements into name:value object
    var data = $form.serializeArray();
    data[data.length] = { name: "MainImage", value: mainImageObj };

    //#2 Create a clean JS Object
    var myObj = {};
    for (var j = 0; j < data.length; j++) {
        myObj[data[j]["name"]] = data[j]["value"];
    }

    AjaxModule.Ajax(url, myObj, options);

Работает! Спасибо, Партик (он же poke)

0 голосов
/ 23 апреля 2020

Ваш json формат неверный .

Вы должны изменить json на

{
  "MainImage": {
    "IsParent": true,
    "ImageUrl": "https://res.cloudinary.com/dzpws1e6vo/image/upload/v1587657844/Businesses/44637/q1lgkqgwpwp7zy1obtpwn.jpg",
    "FileName": "Businesses/44637/qlgkqgwpwp7zy11obtpwn",
    "Width": 960,
    "Height": 720,
    "CreateTime": "2020-04-23T16:04:04Z",
    "Bytes": 181783,
    "ChildImages": [{
        "IsParent": false,
        "ImageUrl": "https://res.cloudinary.com/dzpwse6vo/image/upload/c_crop,g_auto,h_350,q_auto,w_1600/v15876517844/Businesses/44637/qlgkqgwpwp7zy1o1btpwn.jpg",
        "FileName": "Businesses/44637/qlgkqgwpwp7z1y1obtpwn",
        "Width": 960,
        "Height": 350,
        "CreateTime": "2020-04-23T16:04:04Z",
        "Bytes": 78322
    }]
}

или изменить модель ввода на

[HttpPost]
public JsonResult SaveNewBusiness(ImageViewModel imageViewModel)
{

}
...