asp.net-mvc
मॉडल बाइंडिंग
खोज…
परिचय
मॉडल बाइंडिंग HTTP पैरामीटर्स को लेने की प्रक्रिया है, जो आमतौर पर GET अनुरोध के क्वेरी स्ट्रिंग में, या POST बॉडी के भीतर होती है, और इसे किसी ऑब्जेक्ट में लागू किया जाता है, जिसे तब नियंत्रक कार्यों की आवश्यकता के बिना ऑब्जेक्ट-ओरिएंटेड तरीके से मान्य और उपभोग किया जा सकता है। HTTP मापदंडों को पुनः प्राप्त करने के बारे में गहन ज्ञान होना।
दूसरे शब्दों में, मॉडल बाइंडिंग वह है जो एमवीसी में क्रियाओं को अनुमति देता है, या तो पैरामीटर (एस), चाहे वह मूल्य प्रकार हो या वस्तु।
टिप्पणियों
क्रिया में आवृत्ति बनाने का प्रयास करने के लिए, बाइंड मॉडल प्रक्रिया विभिन्न स्थानों में डेटा खोजेगी:
- प्रपत्र डेटा
- रूट डेटा
- क्वेरी स्ट्रिंग
- फ़ाइलें कस्टम (उदाहरण के लिए कुकीज़)
मार्ग मूल्य बंधन
कुछ डिफॉल्ट रूटिंग जैसे {controller=Home}/{action=Index}/{id?}
अगर आपके पास url https://stackoverflow.com/questions/1558902
यह QuestionController पर जाएगा और मूल्य 1558902 एक इंडेक्स एक्शन के आईडी पैरामीटर पर मैप किया जाएगा, अर्थात
public ActionResult Index(int? id){
//id would be bound to id of the route
}
क्वेरी स्ट्रिंग बाइंडिंग
मार्ग बंधन में विस्तार के लिए आप https://stackoverflow.com/questions/1558902?sort=desc
तरह एक यूआरएल था
और {controller=Home}/{action=Index}/{id?}
public ActionResult Index(int? id, string sort){
//sort would bind to the value in the query string, i.e. "desc"
}
वस्तुओं से बांधना
अक्सर आप asp.net-mvc में viewmodel वर्गों के साथ काम कर रहे होंगे और इन पर संपत्तियों को बांधना चाहेंगे। यह व्यक्तिगत मापदंडों के मानचित्रण के समान है।
मान लीजिए कि आपके पास एक सरल दृश्य मॉडल कॉल PostViewModel था
public class PostViewModel{
public int Id {get;set;}
public int SnappyTitle {get;set;}
}
तब आपने http अनुरोध में एक फॉर्म से Id और SnappyTitle के मान पोस्ट किए थे, फिर वे उस मॉडल पर सही मैप करेंगे यदि मॉडल खुद एक्शन पैरामीटर था, जैसे
public ActionResult UpdatePost(PostViewModel viewModel){
//viewModel.Id would have our posted value
}
यह ध्यान देने योग्य है कि बंधन पैरामीटर और संपत्ति के नाम के लिए असंवेदनशील है। जहाँ संभव होगा वहाँ मान भी डालेगा। मैं विशिष्ट उदाहरणों के लिए अधिक धार मामलों को छोड़ रहा हूं
अजाक्स बंधन
ये फॉर्म मूल्य हैं जो POST विधि का उपयोग करके HTTP अनुरोध में जाते हैं। (jQuery पोस्ट अनुरोध सहित)।
कहते हैं कि आपने ajax पोस्ट पसंद किया
$.ajax({
type: 'POST',
url: window.updatePost,
data: { id: 21, title: 'snappy title' },
//kept short for clarity
});
यहाँ दो मान json, id और शीर्षक, मिलान कार्रवाई के लिए बाध्य होंगे, उदा
public JsonResult UpdatePost(int id, string title) {
...
}
सामान्य, सत्र आधारित मॉडल बाध्यकारी
कभी-कभी हमें पूरे मॉडल को संरक्षित करने और इसे कार्रवाई या नियंत्रकों में स्थानांतरित करने की आवश्यकता होती है। इस प्रकार की आवश्यकताओं के लिए सत्र अच्छा समाधान के लिए भंडारण मॉडल। यदि हम इसे एमवीसी के शक्तिशाली मॉडल बाइंडिंग विशेषताओं के साथ जोड़ते हैं तो हमें ऐसा करने का सुंदर तरीका मिलता है। हम तीन आसान चरणों में सामान्य सत्र आधारित मॉडल बाइंडिंग बना सकते हैं:
एक कदम: मॉडल बांधने की मशीन बनाएँ
स्वयं एक मॉडल बाइंडर बनाएं। व्यक्तिगत रूप से मैंने SessionDataModelBinder वर्ग / Infrastructure / ModelBinders फ़ोल्डर में बनाया।
using System;
using System.Web.Mvc;
public class SessionDataModelBinder<TModel>
: IModelBinder
where TModel : class
{
private string SessionKey { get; set; }
public SessionDataModelBinder(string sessionKey)
{
if (string.IsNullOrEmpty(sessionKey))
throw new ArgumentNullException(nameof(sessionKey));
SessionKey = sessionKey;
}
public object BindModel(
ControllerContext controllerContext,
ModelBindingContext bindingContext)
{
// Get model from session
TModel model = controllerContext
.HttpContext
.Session[SessionKey] as TModel;
// Create model if it wasn't found from session and store it
if (model == null)
{
model = Activator.CreateInstance<TModel>();
controllerContext.HttpContext.Session[SessionKey] = model;
}
// Return the model
return model;
}
}
चरण दो: रजिस्टर बाइंडर
अगर हमारे पास नीचे जैसा मॉडल है:
public class ReportInfo
{
public int ReportId { get; set; }
public ReportTypes TypeId { get; set; }
}
public enum ReportTypes
{
NotSpecified,
Monthly, Yearly
}
हम इस मॉडल के लिए सेशन आधारित मॉडल बाइंडर को Global.asax में Application_Start पद्धति में पंजीकृत कर सकते हैं:
protected void Application_Start()
{
.........
// Model binders.
// Remember to specy unique SessionKey
ModelBinders.Binders.Add(typeof(ReportInfo),
new SessionDataModelBinder<ReportInfo>("ReportInfo"));
}
चरण तीन: इसका उपयोग करें!
अब हम अपने कार्यों में पैरामीटर जोड़कर इस मॉडल बाइंडर से लाभ उठा सकते हैं:
public class HomeController : Controller
{
public ActionResult Index(ReportInfo reportInfo)
{
// Simply set properties
reportInfo.TypeId = ReportTypes.Monthly;
return View();
}
public ActionResult About(ReportInfo reportInfo)
{
// reportInfo.TypeId is Monthly now because we set
// it previously in Index action.
ReportTypes currentReportType = reportInfo.TypeId;
return View();
}
}
PostModel पर बाध्यकारी रोकें
विचार (पोस्ट) मॉडल:
public class User
{
public string FirstName { get; set; }
public bool IsAdmin { get; set; }
}
इस तरह से एक दृश्य के साथ:
@using (Html.BeginForm()) {
@Html.EditorFor(model => model.FirstName)
<input type="submit" value="Save" />
}
एक दुर्भावनापूर्ण उपयोगकर्ता को IsAdmin को असाइन करने से रोकने के लिए आप कार्रवाई में Bind
विशेषता का उपयोग कर सकते हैं:
[HttpPost]
public ViewResult Edit([Bind(Exclude = "IsAdmin")] User user)
{
// ...
}
फाइल अपलोड
नमूना:
public class SampleViewModel
{
public HttpPostedFileBase file {get;set;}
}
राय:
@model HelloWorldMvcApp.SampleViewModel
@using (Html.BeginForm("Index","Home",FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="form-group">
@Html.TextBoxFor(model => model.file, new {@class="form-control", type="file"})
@Html.ValidationMessageFor(model => model.file)
</div>
<button type="submit" class="btn btn-success submit">Upload</button>
}
क्रिया:
[HttpPost]
public ActionResult Index(SampleViewModel model)
{
if (model.file.ContentLength > 0)
{
string fileName = Path.GetFileName(model.file.FileName);
string fileLocation = "~/App_Data/uploads/"+ fileName;
model.file.SaveAs(Server.MapPath(fileLocation));
}
return View(model);
}
मॉडल बाइंडर का उपयोग करके गतिशील स्वरूपों के साथ मैन्युअल रूप से दिनांक फ़ील्ड को मान्य करना
यदि अलग-अलग उपयोगकर्ताओं को अलग-अलग डेटाइम प्रारूप की आवश्यकता होती है, तो आपको प्रारूप के अनुसार अपनी आने वाली तारीख स्ट्रिंग को वास्तविक तिथि पर पार्स करने की आवश्यकता हो सकती है। इस मामले में यह स्निपेट आपकी मदद कर सकता है।
public class DateTimeBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
DateTime date;
var displayFormat = Session["DateTimeFormat"];
if (value.AttemptedValue != "")
{
if (DateTime.TryParseExact(value.AttemptedValue, displayFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out date))
{
return date;
}
else
{
bindingContext.ModelState.AddModelError(bindingContext.ModelName, "Invalid date format");
}
}
}
return base.BindModel(controllerContext, bindingContext);
}