DefaultModelBinder behaviour when property absent from request

半城伤御伤魂 提交于 2020-01-06 05:35:08

问题


I have a model like the following:

public class TestViewModel
{
  string UpdateProperty { get; set; }
  string IgnoreProperty { get; set; }
  ComplexType ComplexProperty { get; set; }
}

where

public class ComplexType
{
  long? Code { get; set; }
  string Name { get; set; }
}

My controller action:

public Edit(int id, FormColleciton formCollection)
{
  var model = service.GetModel(id);
  TryUpdateModel(model);

  //...
}

When calling the Edit action I have a formCollection parameter containing only a key/value for UpdateProperty.

After the call to TryUpdateModel UpdateProperty is set correctly, IgnoreProperty is left un-touched but ComplexProperty is set to null, even if it previously had a value.

Should TryUpdateModel() only modify properties that are a part of the request? If this is not the case what is the best way to work around this so ComplexProperty is only modified if it is included in the request?


After it was pointed out by Darin that the test case above didn't demonstrate the problem I have added a scenario where this problem really occurs:

public class TestViewModel
{
    public List<SubModel> List { get; set; }
}

public class SubModel
{
    public ComplexType ComplexTypeOne { get; set; }
    public string StringOne { get; set; }
}

public class ComplexType
{
    public long? Code { get; set; }
    public string Name { get; set; }
}

Controller Action:

public ActionResult Index()
{
    var model = new TestViewModel
                    {
                        List = new List<SubModel> { 
                            new SubModel{
                                ComplexTypeOne = new ComplexType{Code = 1, Name = "5"},
                                StringOne = "String One"
                            } 
                        }
                    }; 

    if (TryUpdateModel(model)) { } 

    return View(model);
}

Sending this request:

/Home/Index?List[0].StringOne=test

updates SubModel.StringOne property but sets ComplexTypeOne to null, even though it is not included in the request.

Is this expected behaviour (given this does not happen unless an enumerable of complex types is used)? How best to work around this?


回答1:


There must be something wrong with your test case as I was unable to reproduce it. Here's what I tried:

Model (notice that I use public properties):

public class TestViewModel
{
    public string UpdateProperty { get; set; }
    public string IgnoreProperty { get; set; }
    public ComplexType ComplexProperty { get; set; }
}

public class ComplexType
{
    public long? Code { get; set; }
    public string Name { get; set; }
}

Controller:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        var model = new TestViewModel
        {
            IgnoreProperty = "to be ignored",
            UpdateProperty = "to be updated",
            ComplexProperty = new ComplexType
            {
                Code = 1,
                Name = "5"  
            }
        };

        if (TryUpdateModel(model))
        {

        }
        return View();
    }
}

Now I send the following request: /home/index?UpdateProperty=abc and inside the condition only the UpdateProperty is modified with the new value from the query string. All other properties, including the complex property, are left untouched.

Also notice that the FormCollection action parameter is useless.



来源:https://stackoverflow.com/questions/6914448/defaultmodelbinder-behaviour-when-property-absent-from-request

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!