簡體   English   中英

Ajax 傳遞空值但控制器在 ASP.NET MVC 中為空

[英]Ajax passing empty value but Controller get null in ASP.NET MVC

我正在使用ASP.NET MVC ,但從Ajax發送到我的控制器的值有問題。

假設我有這樣的SampleViewModel

public class SampleViewModel
{
    private string _firstName = string.Empty;

    public SampleViewModel()
    {
        _firstName = string.Empty;
    }

    public string FirstName
    {
        get { return _firstName; }
        set { _firstName = value ?? string.Empty; }
    }

    public string LastName { get; set; }

    public string FullName { get; set; }
}

控制器

[HttpPost]
public JsonResult ActionSubmit(SampleViewModel model)
{               
    var result = "";

    if(model.FirstName == null)
          result += "\nFirstName is null";

    if(model.LastName == null)
          result += "\nLastName is null";

    return Json(result);
}

阿賈克斯

$('.submit').click(function() {
        $.ajax({
            url: '@Url.RouteUrl(new{ action="ActionSubmit", controller="Home"})',
            data: JSON.stringify({ FirstName: '', LastName: '', FullName: 'Phong_Nguyen' }),
                  // Even though I use { FirstName: '', LastName: '', FullName: 'Phong_Nguyen' } without JSON.stringify
            type: 'POST',
            dataType: 'json',
            contentType: "application/json; charset=utf-8",
            success: function(resp) {
                   alert(resp);
            }});
         });

如您所見,我發送了空值,但在控制器的一端,我得到了空值(響應值始終為“LastName 為空”): 在此處輸入圖片說明

  1. 為什么在 Ajax 中我發送empty ,我的控制器中得到null值?

  2. 有沒有更好的方法和更優雅的方式來解決我的問題,如下所示?

public string FirstName
{
   get { return _firstName; }
   set { _firstName = value ?? string.Empty; }
}

為什么在 Ajax 中我發送空值時,我的控制器中得到null值?

string是一個引用類型,它的默認值為null 如果請求中未提供任何值,則ModelBinder將屬性設置為其默認值。

有沒有更好的方法和更優雅的方式來解決我的問題,如下所示?

  1. 您可以使用[DisplayFormat(ConvertEmptyStringToNull = false)]注釋該屬性,以便保留空字符串值。

  2. 您可以編寫一個自定義ModelBinder ,將ConvertEmptyStringToNull設置為false ,並全局應用它。

public class NullStringModelBinder : DefaultModelBinder {
    public override object BindModel(ControllerContext controllerContext,
                                     ModelBindingContext bindingContext) {
        bindingContext.ModelMetadata.ConvertEmptyStringToNull = false;
        return base.BindModel(controllerContext, bindingContext);
    }
}

//register it in Application_Start()
ModelBinders.Binders.Add(typeof(string), new NullStringModelBinder());

此特定更改已記錄在此處,它是MVC 1.0的重大更改之一。 這種將空字符串綁定到null的邏輯由DefaultModelBinder使用的ModelMetadata.ConvertEmptyStringToNull屬性控制。

現在,如果您不想注釋所有屬性,則可以創建自定義模型綁定器:

public class EmptyStringModelBinder : DefaultModelBinder 
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        bindingContext.ModelMetadata.ConvertEmptyStringToNull = false;
        Binders = new ModelBinderDictionary() { DefaultBinder = this };
        return base.BindModel(controllerContext, bindingContext);
    }
}

並將其設置在您的Global.asax

ModelBinders.Binders.DefaultBinder = new EmptyStringModelBinder();

或者在您的具體行動中:

[HttpPost]
public JsonResult ActionSubmit([ModelBinder(typeof(EmptyStringModelBinder))SampleViewModel model)

為什么這樣做?

這樣做是因為一個默認值stringnull因為stringreference type ,默認值,所有引用類型為null 因此,框架的這種變化可能是合理的。 但另一方面,我們應該盡量避免空值,因此我們需要編寫一個自定義模型綁定器來避免這種情況。

有個問題,為什么字符串類型默認值是null而不是空字符串? . 您可以查看此內容以了解更多有關進行此更改的原因。

根據@Anton:在c# 8.0您可以打開 null 檢查以避免NullReferenceException並將引用類型設置為默認值而不是null

我決定總結@Rahul Sharma@rhytonix 的答案,並為您提供示例和更詳細的解釋。

  1. 為什么在 Ajax 中我發送空值時,我的控制器中得到空值?

這僅僅是因為MVC 2.0默認將字符串初始化為 null。 更准確地說,如果empty字符串意味着沒有值,那么 .NET 會設置其默認值。 默認字符串(屬於引用類型)為null

模型字符串屬性綁定中斷更改中的更多詳細信息

  1. 有沒有更好的方法和更優雅的方式來解決我的問題,如下所示?

有一些方法可以將 String 屬性綁定為string.Empty而不是null

1. 從 C# 6 開始,您可以使用DefaultValueAttribute使自動屬性具有如下所示的初始值

public string LastName => string.Empty; 

基本上,這種方式與帖子中提到的OP的解決方案相同,只是更優雅。

2. 通過從DefaultModelBinder繼承並將內部ModelMetaData對象上的ConvertEmptyStringToNull值更改為 false 來自定義IModelBinder的默認實現。

public sealed class EmptyStringModelBinder : DefaultModelBinder 
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        bindingContext.ModelMetadata.ConvertEmptyStringToNull = false;
        return base.BindModel(controllerContext, bindingContext);
    }
}

然后在Global.asax.cs Application_Start()方法中你需要像下面這樣完成

protected void Application_Start()
{
    ModelBinders.Binders.DefaultBinder = new EmptyStringModelBinder();
    RegisterRoutes( RouteTable.Routes );
}

3. 使用DisplayFormatAttribute.ConvertEmptyStringToNull 屬性,如下所示

[DisplayFormat(ConvertEmptyStringToNull = false)]
public string LastName { get; set; }

僅僅因為在ModelMetadata 中

如果空字符串值自動轉換為null ,則為true 否則為false 默認為true

當你在 C# 中聲明一個字符串變量時,它的值是null直到被賦值。

當通過表單提交發送數據時,任何未輸入信息的字段都將作為空字符串發送。 不提供任何信息的最佳模擬是null ,因此它將這些值設置為null (或者更有可能根本不設置值)。

MVC 無法區分空字符串(因為沒有提供信息)和空字符串(因為這是在 JavaScript 傳輸之前分配的值)。 它只知道其中一個字段沒有信息,因此該值應為null

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM