InvalidOperationException Microsoft.AspNetCore.Mvc.ModelBinding.Binders.ComplexTypeModelBinder.CreateModel (ModelBindingContext bindingContext) - PullRequest
1 голос
/ 19 сентября 2019

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

I get an exception when I execute Post. 

Это мой вид редактирования бритвы.

<h1>Edit:</h1>






        <form method="post">




        <label asp-for="EditClient.Name"> </label>
        <input asp-for="EditClient.Name"
               class="form-control"
               readonly="readonly" />



        <h3 class="text text-info">Pull Configuration</h3>
        <div>

            <label asp-for="EditClient.Pull.Protocol"> </label>
            <input asp-for="EditClient.Pull.Protocol" class="form-control" />
            <span asp-validation-for="EditClient.Pull.Protocol" class="text-danger"></span>

            <label asp-for="EditClient.Pull.Host"> </label>
            <input asp-for="EditClient.Pull.Host" class="form-control" />
            <span asp-validation-for="EditClient.Pull.Host" class="text-danger"></span>


            <label asp-for="EditClient.Pull.User"> </label>
            <input asp-for="EditClient.Pull.User" class="form-control" />
            <span asp-validation-for="EditClient.Pull.User" class="text-danger"></span>

            <label asp-for="EditClient.Pull.Password"> </label>
            <input asp-for="EditClient.Pull.Password" class="form-control" />
            <span asp-validation-for="EditClient.Pull.Password" class="text-danger"></span>


            <label asp-for="EditClient.Pull.PrivateKeyPath"> </label>
            <input asp-for="EditClient.Pull.PrivateKeyPath" class="form-control" />
            <span asp-validation-for="EditClient.Pull.PrivateKeyPath" class="text-danger"></span>

            <label asp-for="EditClient.Pull.Port"> </label>
            <input asp-for="EditClient.Pull.Port" class="form-control" />
            <span asp-validation-for="EditClient.Pull.Port" class="text-danger"></span>


            <label asp-for="EditClient.Pull.RemoteDirectory"> </label>
            <input asp-for="EditClient.Pull.RemoteDirectory" class="form-control" />
            <span asp-validation-for="EditClient.Pull.RemoteDirectory" class="text-danger"></span>


            <label asp-for="EditClient.Pull.IsDecrypt"> </label>
            <input asp-for="EditClient.Pull.IsDecrypt" class="form-control" />
            <span asp-validation-for="EditClient.Pull.IsDecrypt" class="text-danger"></span>



        </div>


        <h3 class="text text-info">Push Configuration</h3>
        <label asp-for="EditClient.Push.Protocol"> </label>
        <input asp-for="EditClient.Push.Protocol" class="form-control" />
        <span asp-validation-for="EditClient.Push.Protocol" class="text-danger"></span>

        <label asp-for="EditClient.Push.Host"> </label>
        <input asp-for="EditClient.Push.Host" class="form-control" />
        <span asp-validation-for="EditClient.Push.Host" class="text-danger"></span>


        <label asp-for="EditClient.Push.User"> </label>
        <input asp-for="EditClient.Push.User" class="form-control" />
        <span asp-validation-for="EditClient.Pull.User" class="text-danger"></span>

        <label asp-for="EditClient.Push.Password"> </label>
        <input asp-for="EditClient.Push.Password" class="form-control" />
        <span asp-validation-for="EditClient.Pull.Password" class="text-danger"></span>


        <label asp-for="EditClient.Push.PrivateKeyPath"> </label>
        <input asp-for="EditClient.Push.PrivateKeyPath" class="form-control" />
        <span asp-validation-for="EditClient.Pull.PrivateKeyPath" class="text-danger"></span>

        <label asp-for="EditClient.Push.Port"> </label>
        <input asp-for="EditClient.Push.Port" class="form-control" />
        <span asp-validation-for="EditClient.Pull.Port" class="text-danger"></span>


        <label asp-for="EditClient.Push.RemoteDirectory"> </label>
        <input asp-for="EditClient.Push.RemoteDirectory" class="form-control" />
        <span asp-validation-for="EditClient.Pull.RemoteDirectory" class="text-danger"></span>

        <label asp-for="EditClient.Push.IsZip"> </label>
        <input asp-for="EditClient.Push.IsZip" class="form-control" />
        <span asp-validation-for="EditClient.Push.IsZip" class="text-danger"></span>



        <label asp-for="EditClient.Push.IsEncrypt"> </label>
        <input asp-for="EditClient.Push.IsEncrypt" class="form-control" />
        <span asp-validation-for="EditClient.Push.IsEncrypt" class="text-danger"></span>

        <button type="submit">
            Submit
        </button>
    </form>







    This is my EditModel
    ``````````````````````````````````````````````````

    public class EditModel : PageModel
        {
            private readonly IClientConfiguration _config;



            [BindProperty(SupportsGet = false)]
            public ClientConfig EditClient { get; set; } 





            public EditModel(IClientConfiguration config)
            {
                this._config = config;

            }


            public IActionResult OnPost()
            {
                var _editedClient = 
                    new ClientConfig(this.EditClient.Name, this.EditClient.Email, this.EditClient.Push, this.EditClient.Pull);


                if(this._config.GetByName(_editedClient.Name) == null)
                {
                    this._config.Add(_editedClient);
                }
                else
                {
                    this._config.Edit(_editedClient);
                }

                return this.RedirectToPage("/DropBox/Detail", new { name = _editedClient.Name }); 
            }
            public IActionResult OnGet(string name)
            {
                this.EditClient = this._config.GetByName(name);


                return this.Page();
            }
        }









    This is my type
    ```````````````````````````````````````````````````````````
    [JsonObject]
        public class ClientConfig
        {

            [JsonProperty]
            public string Name { get; }

            [JsonProperty]
            public IEnumerable<string> Email { get; }


            [JsonProperty]
            public PushConfig Push { get; }

            [JsonProperty]
            public PullConfig Pull { get; }



            [JsonConstructor]
            public ClientConfig(string name, IEnumerable<string> email, PushConfig push, PullConfig pull)
            {
                this.Name = name;
                this.Email = email;
                this.Push = push;
                this.Pull = pull;
            }






        }


    This is my IClientConfig Interface and the class who implements it
    `````````````````````````````````````````````````````````````````````

     public class InMemoryClientConfig : IClientConfiguration
        {
            public List<ClientConfig> GetAll()
            {
                return this.LoadClientsConfig().Clients
                    .ToList();
            }
            public ClientConfig Add(ClientConfig clientConfig)
            {
                var allClients = this.GetAll();

                var exist = allClients.Contains(clientConfig);

                if(!exist)
                {
                    this.GetAll().Add(clientConfig);

                    return clientConfig;
                }

                return clientConfig; 


            }

            public ClientConfig Edit(ClientConfig clientConfig)
            {
                var _edit = this.GetByName(clientConfig.Name); 


                if (_edit != null)
                this.GetAll().Remove(_edit);

                this.GetAll()
                    .Add(new ClientConfig(clientConfig.Name, clientConfig.Email, clientConfig.Push, clientConfig.Pull));
                return clientConfig;
            }


            public ClientConfig Delete(int id)
            {
                throw new NotImplementedException();
            }



            Config LoadClientsConfig()
            {
                var deserialize = File.ReadAllText(@"C:\...\Path\ToJsonFile");
                return JsonConvert.DeserializeObject<Config>(deserialize);
            }
            public ClientConfig GetByName(string name)
            => this.GetAll
                     ().SingleOrDefault(x => x.Name == name);
        }






Дочерняя проблема возникает из свойства ClientConfig EditClient, расположенного в строке класса EditModel: PageModel # 18.

get работает нормально, но когда я пытаюсь опубликовать изменения, внесенные на странице формы, я получаю InvalidOperationException Не удалось создать экземпляр типа 'ProjectName.Core.ClientConfig Сложные типы, связанные с моделью, не должны быть абстрактными или значениями идолжен иметь конструктор без параметров.В качестве альтернативы, задайте для параметра 'EditClient' ненулевое значение по умолчанию.

Я застрял на этом в течение дня или около того и рассмотрел другие вопросы стека с ответами, но я не понимаю предоставленные ответы, терминологию илипримеры.

Извините, если я не прояснил свой вопрос, но это в меру моих возможностей.

Любая помощь будет принята с благодарностью.

Еще раз спасибо.

1 Ответ

0 голосов
/ 25 сентября 2019

Наконец-то понял.

Сделайте следующее: 1. Убедитесь, что имя вашего ярлыка соответствует свойству, с которым вы хотите связать.«

Перегрузка пустого конструктора для типа, к которому вы привязываете.

Передайте свойство модели привязки из представления бритвы в качестве аргумента методу Post, и don 'не забудьте передать его из вида бритвы, используя помощники тегов.

Модель должна иметь Get;Установлен;для реквизита, с которым вы работаете.

Свойство модели привязки, добавьте атрибут [BindProperty (Support Get = False)] и убедитесь, что у вас есть get;установлен;

Дайте мне знать, если вам нужен пример кода для этого.

Надеюсь, это кому-нибудь поможет.Вола!

...