ASP.NET MVC請求參數字符串之區分空與NULL


開發中經常會寫增刪改查的功能,這里記錄下在更新操作時遇到的一個問題。

假設一個模型對應數據庫中某一張表,在更新時便需要區分是一次性更新全部字段還是僅更新部分字段。希望能做到傳遞某個參數時便更新,未傳遞時不更新。

先定義一個用戶模型,如下:

public class UserModel
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Address { get; set; }
}

服務端以這種方式來接收:

public IActionResult Update(UserModel user)
{
    // 執行數據庫更新操作
    return Content(user.Id + user.Name + user.Address);
}

然后客戶端以下面的方式來請求(這里用GET方式):

/user/update?id=1&address=hang&name=Hale
/user/update?id=1&address=hang&name=
/user/update?id=1&address=hang

上面有三種傳參方式,一般情況下沒有問題,但對於第二種形式,&name= 的方式,原本是希望將name字段更新為空值,但是在Action里接收時會發現,user.Name == null 。這樣便無法區分是要將Name更新為空值,還是不做更新。

ModelBinder的方式

默認MVC在構造參數模型時沒有區分這兩種情況,要實現我們的需求就需要自定義一個ModelBinder。定義一個類,並實現IModelBinder接口即可。

public class StringBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        throw new NotImplementedException();
    }
    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.FieldName);

        if (valueProviderResult == ValueProviderResult.None)
            return Task.CompletedTask;

        bindingContext.Result = ModelBindingResult.Success(valueProviderResult.FirstValue);
        return Task.CompletedTask;
    }
}

它提供兩個方法來綁定模型,一個同步的一個異步的。我用的 asp.net core 是調用的異步版方法,所以這里僅實現了BindModelAsync。

以這種方式來用這個StringBinder:

public class UserModel
{
    public int Id { get; set; }
    [ModelBinder(typeof(StringBinder))]
    public string Name { get; set; }
    [ModelBinder(typeof(StringBinder))]
    public string Address { get; set; }
}

這樣,再以上面第二種方式傳參時,便會發現user.Name == "",而不是 user.Name == null。
這個StringBinder還可以直接用在Action的參數上:

public IActionResult Update(UserModel user, [ModelBinder(typeof(StringBinder))]string v, string v2)
{
    return Content(user.Id + user.Name + v + v2);
}

這里參數 v 和 v2,一個指定了Binder一個未指定,以下面方式調用以下即可看出區別:

/user/update?id=1&address=&name=Ingo&v=&v2=

會發現 user.Address == "" ,v == "", v2 == null。

簡單的方式

除了自定義ModelBinder的方式,還可以通過直接修改屬性的set訪問器的辦法來區分null和空字符串。
修改下UserModel的代碼,新增一個Phone成員:

private string phone;
public string Phone
{
    get => phone;
    set => phone = string.IsNullOrEmpty(value) ? string.Empty : value;
}

采用與上面相同的方式傳值,會發現當傳遞&phone=時,user.Phone == "", 同樣也能區分phone是傳遞的空字符串還是沒傳遞phone參數。
因為mvc在收到&phone=參數時會調用set訪問器,只是value為null。而未收到&phone=xx參數時,不會調用set訪問器,所以用這種辦法也可以區分空值和null。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM