[英]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 為空”):
題
為什么在 Ajax 中我發送empty
,我的控制器中得到null
值?
有沒有更好的方法和更優雅的方式來解決我的問題,如下所示?
public string FirstName
{
get { return _firstName; }
set { _firstName = value ?? string.Empty; }
}
為什么在 Ajax 中我發送空值時,我的控制器中得到
null
值?
string
是一個引用類型,它的默認值為null
。 如果請求中未提供任何值,則ModelBinder
將屬性設置為其默認值。
有沒有更好的方法和更優雅的方式來解決我的問題,如下所示?
您可以使用[DisplayFormat(ConvertEmptyStringToNull = false)]
注釋該屬性,以便保留空字符串值。
您可以編寫一個自定義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)
為什么這樣做?
這樣做是因為一個默認值string
是null
因為string
是reference type
,默認值,所有引用類型為null
。 因此,框架的這種變化可能是合理的。 但另一方面,我們應該盡量避免空值,因此我們需要編寫一個自定義模型綁定器來避免這種情況。
有個問題,為什么字符串類型的默認值是null而不是空字符串? . 您可以查看此內容以了解更多有關進行此更改的原因。
根據@Anton:在c# 8.0
您可以打開 null 檢查以避免NullReferenceException
並將引用類型設置為默認值而不是null
我決定總結@Rahul Sharma和@rhytonix 的答案,並為您提供示例和更詳細的解釋。
- 為什么在 Ajax 中我發送空值時,我的控制器中得到空值?
這僅僅是因為MVC 2.0
默認將字符串初始化為 null。 更准確地說,如果empty
字符串意味着沒有值,那么 .NET 會設置其默認值。 默認字符串(屬於引用類型)為null
。
模型字符串屬性綁定中斷更改中的更多詳細信息
- 有沒有更好的方法和更優雅的方式來解決我的問題,如下所示?
有一些方法可以將 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.