开发者

DefaultModelBinder behaviour when property absent from request

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 c开发者_如何学运维alling 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?


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜