MVC 自定義模型繫結器,從表單對模型進行賦值

2022-01-13 07:45:04 字數 2965 閱讀 1046

一、奇葩的問題

之前自己造輪子的時候,遇到乙個很奇怪的問題,雖然需求很奇葩,但是還是嘗試解決了一下

當提交的表單裡包含多個重複名稱的字段的時候,例如

html

如果需要模型在action進行接收,那麼通常的解決方案是用乙個 ienumerable 型別或其派生型別來接收資料,以保證資料的完成性,例如這樣乙個模型

public

class

test

}

model

一般來講這麼做沒啥問題,可是問題來了

如果我需要將結果以逗號(,)分割並輸出,那麼我就需要寫這樣一行** string.join("

,", model.test); ,無論是在**。

如果不在模型欄位上做字串拼接操作的,還會導致這個模型無法復用。而且**看起來很不優雅。

二、思考問題

我把這個問題也發到了博問上.net mvc 模型接收引數問題

普遍得到的答案都是我上面說到的解決方式,似乎不是我想要的。

嘗試思考一下。

標準的http的request接收到的時候,對與mvc來說他只是乙個form或者querystring(如果理解有誤,歡迎指正),那麼mvc框架是怎麼做到將乙個表單繫結到乙個模型上呢?

為什麼 httpcontext.request.form 中對應的字段倒是完成了字串拼接的?

為什麼表單和模型的賦值不一樣?表單裡的值我能不能用?

帶著問題猛戳了一番度娘後,發現了乙個驚喜的東西,模型繫結器(modelbinder)

概念我就不貼了,見這個大神的部落格 asp.net mvc5 modelbinder

這一篇是core的, asp.net core mvc model binding: custom binders

三、解決方案

1、建立乙個自己的模型繫結器

framework:

public

class

testmodelbinder : defaultmodelbinder, imodelbinder

}

core:

public

class

testmodelbinder : imodelbinder

}

只要在注釋的地方,對模型需要賦值的字段進行操作就可以了

ps:具體操作就仁者見仁智者見智了,簡單說一下我自己的做法,反射遍歷模型型別為string的字段,如果模型字段值與表單同名的值不一致,由表單從新給字段賦值。

這個做法的效率有待提公升,不過目前先這麼解決。

好了模型繫結器有了,不過現在還不能用。

2、定義模型繫結器的provider

這個方法在上面那個大神的部落格裡有寫,我在這裡再囉嗦一下

framework:

public

class

testmodelbinderprovider : imodelbinderprovider

return

null

; }

}

這裡傳入的type是模型本身的type,用來過濾對拿一些模型生效,一般會使用預設繫結器 defaultmodelbinder 的。

core:

public

class

testmodelbinderprovider : imodelbinderprovider

return

null

; }

}

除了引數不太一樣,兩個版本基本長得一毛一樣。

3、全域性註冊

定義為全域性的模型繫結器就可以在所有模型繫結的時候啟動。無需再加任何其他東西,但是同時面臨乙個問題就是使用原生的繫結器需要在引數上單獨宣告。

framework是在global.asax裡面

public

class

}

core是在startup.cs裡

public

void

configureservices(iservicecollection services)

)

4、定義模型繫結屬性

在特殊的繫結器不多的情況下我們可以選擇將繫結器定義為屬性

framework:

[attributeusage(attributetargets.parameter, allowmultiple = false, inherited = false

)]

public

class

formformatattribute : custommodelbinderattribute

}

core:

[attributeusage(attributetargets.parameter,allowmultiple = false, inherited = false

)]

public

class

testmodelbinderattribute : modelbinderattribute

}

看起來基本也是一毛一樣

屬性的呼叫方法兩個是一致的,在引數前面加上 [testmodelbinder] 就可以了。

總結:

經過一番折騰,模型繫結器搞定了,也能更加優雅繫結變數了。也不需要那麼一堆什麼拼接字串啊,額外屬性啊,之類的。

但是需要注意一點,core的繫結器沒有預設基類(也可能是我沒找到,如果找到了,如果有找到的麻煩歡迎分享),所以不能像framework一樣先讓預設的處理,處理完再處理。而是需要全部都由開發人員手動處理。

Django 自定義模型管理器

我們常常在view檢視裡查詢某個模型的資料的時候,通常的是這樣查詢的 上述每個模型類中都有乙個objects類屬性,可以叫他模型管理器。它由django自動生成,型別為django.db.models.manager.manager.我們可以將objects看做manager類的例項化物件,而上述的...

自定義MVC框架 封裝控制器層

控制器的作用是作為模型於檢視之間的橋梁,細分的話有兩個 建立模型類時時按照表劃分的,也就是說一張表對應乙個模型類 控制器類應該建立在controller 目錄下,每個類就是乙個控制器,我們稱為控制器類 控制器檔案的命名規範 1 功能名稱 controller.class.php 2 控制器名稱也採用...

自定義表單 列表欄位的資料來源繫結

記得剛開始使用grid時,如果想對乙個類別字段進行顯示,往往需要在後台寫乙個方法,通過頁面呼叫的方式來顯示字段資訊,當然這也只是一種方式,有的可能在資料返回時已經作了處理,處理方式除了sql聯合查詢外,一般都要有乙個資料來源的存在,能夠靈活的繫結資料來源,是列表功能快速開發的乙個基本要求。自定義列表...