asp.net mvc एएसपी.नेट एमवीसी आंशिक विचार: इनपुट नाम उपसर्ग




asp.net-mvc spark-view-engine (8)

मान लीजिए मेरे पास व्यूमोडेल जैसा है

public class AnotherViewModel
{
   public string Name { get; set; }
}
public class MyViewModel
{
   public string Name { get; set; }
   public AnotherViewModel Child { get; set; }
   public AnotherViewModel Child2 { get; set; }
}

दृश्य में मैं आंशिक रूप से प्रस्तुत कर सकता हूं

<% Html.RenderPartial("AnotherViewModelControl", Model.Child) %>

आंशिक में मैं करूँगा

<%= Html.TextBox("Name", Model.Name) %>
or
<%= Html.TextBoxFor(x => x.Name) %>

हालांकि, समस्या यह है कि मॉडल बाइंडर ठीक से काम करने के लिए दोनों नाम = "नाम" प्रस्तुत करेंगे जबकि मुझे नाम = "Child.Name" होना चाहिए। या, नाम = "Child2.Name" जब मैं एक ही आंशिक दृश्य का उपयोग करके दूसरी संपत्ति प्रस्तुत करता हूं।

मैं अपना आंशिक दृश्य स्वचालित रूप से आवश्यक उपसर्ग को कैसे पहचानूं? मैं इसे पैरामीटर के रूप में पास कर सकता हूं लेकिन यह बहुत असुविधाजनक है। यह तब भी बदतर है जब मैं उदाहरण के लिए इसे पुन: प्रस्तुत करना चाहता हूं। कॉलिंग लैम्ब्डा अभिव्यक्ति के स्वचालित पुन: संयोजन के साथ उपसर्ग, या इससे भी बेहतर, आंशिक विचारों को प्रस्तुत करने का कोई तरीका है ताकि

<% Html.RenderPartial("AnotherViewModelControl", Model.Child) %>

स्वचालित रूप से सही "बच्चा" जोड़ देगा। जेनरेट नाम / आईडी तारों के लिए उपसर्ग?

मैं 3-डी पार्टी व्यू इंजन और पुस्तकालयों सहित किसी भी समाधान को स्वीकार कर सकता हूं - मैं वास्तव में स्पार्क व्यू इंजन (मैं अपने मैक्रोज़ का उपयोग करके समस्या को हल करता हूं) और एमवीसी कोंट्रिब का उपयोग करता हूं, लेकिन वहां कोई समाधान नहीं मिला। एक्सफॉर्म, इनपुटबिल्डर, एमवीसी वी 2 - इस कार्यक्षमता प्रदान करने वाला कोई भी टूल / अंतर्दृष्टि बहुत अच्छा होगा।

वर्तमान में मैं इसे स्वयं कोडिंग करने के बारे में सोचता हूं लेकिन यह समय की बर्बादी की तरह लगता है, मुझे विश्वास नहीं है कि यह छोटी चीजें पहले ही लागू नहीं हुई हैं।

बहुत सारे मैन्युअल समाधान मौजूद हो सकते हैं, और उनमें से सभी का स्वागत है। उदाहरण के लिए, मैं अपने आंशिक को IPartialViewModel <T> {पब्लिक स्ट्रिंग उपसर्ग; टी मॉडल; }। लेकिन मैं कुछ मौजूदा / अनुमोदित समाधान पसंद करेंगे।

अद्यतन: here कोई जवाब नहीं है जैसा कोई जवाब नहीं here


यह एक पुराना सवाल है, लेकिन किसी भी समाधान के लिए यहां पहुंचने के लिए, EditorFor का उपयोग करने पर विचार करें, जैसा कि https://.com/a/29809907/456456 में एक टिप्पणी में सुझाया गया है। आंशिक दृश्य से एक संपादक टेम्पलेट में स्थानांतरित करने के लिए, इन चरणों का पालन करें।

  1. सत्यापित करें कि आपका आंशिक दृश्य ComplexType से जुड़ा हुआ है।

  2. अपने आंशिक दृश्य को वर्तमान दृश्य फ़ोल्डर के उपफ़ोल्डर संपादक टेम्पलेट्स या साझा फ़ोल्डर में ले जाएं। अब, यह एक संपादक टेम्पलेट है।

  3. @Html.Partial("_PartialViewName", Model.ComplexType) को @Html.EditorFor(m => m.ComplexType, "_EditorTemplateName") । संपादक टेम्पलेट वैकल्पिक है यदि यह जटिल प्रकार के लिए एकमात्र टेम्पलेट है।

एचटीएमएल इनपुट तत्वों को स्वचालित रूप से ComplexType.Fieldname नाम दिया जाएगा।


आप इस द्वारा एचटीएमएल सहायक वर्ग का विस्तार कर सकते हैं:

using System.Web.Mvc.Html


 public static MvcHtmlString PartialFor<TModel, TProperty>(this HtmlHelper<TModel> helper, System.Linq.Expressions.Expression<Func<TModel, TProperty>> expression, string partialViewName)
    {
        string name = ExpressionHelper.GetExpressionText(expression);
        object model = ModelMetadata.FromLambdaExpression(expression, helper.ViewData).Model;
        var viewData = new ViewDataDictionary(helper.ViewData)
        {
            TemplateInfo = new System.Web.Mvc.TemplateInfo
            {
                HtmlFieldPrefix = name
            }
        };

        return helper.Partial(partialViewName, model, viewData);

    }

और बस इसे अपने विचारों में उपयोग करें:

<%= Html.PartialFor(model => model.Child, "_AnotherViewModelControl") %>

और आप देखेंगे कि सबकुछ ठीक है!


आप रेंडरपार्टियल के लिए एक सहायक जोड़ सकते हैं जो उपसर्ग लेता है और इसे व्यूडेटा में पॉप करता है।

    public static void RenderPartial(this HtmlHelper helper,string partialViewName, object model, string prefix)
    {
        helper.ViewData["__prefix"] = prefix;
        helper.RenderPartial(partialViewName, model);
    }

फिर एक और सहायक जो व्यूडेटा मान को जोड़ता है

    public static void GetName(this HtmlHelper helper, string name)
    {
        return string.Concat(helper.ViewData["__prefix"], name);
    }

और इसलिए दृश्य में ...

<% Html.RenderPartial("AnotherViewModelControl", Model.Child, "Child.") %>

आंशिक रूप से ...

<%= Html.TextBox(Html.GetName("Name"), Model.Name) %>

एमवीसी 2 का उपयोग करके आप इसे प्राप्त कर सकते हैं।

दृढ़ता से टाइप किया गया दृश्य यहां दिया गया है:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MvcLearner.Models.Person>" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Create
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <h2>Create</h2>

    <% using (Html.BeginForm()) { %>
        <%= Html.LabelFor(person => person.Name) %><br />
        <%= Html.EditorFor(person => person.Name) %><br />
        <%= Html.LabelFor(person => person.Age) %><br />
        <%= Html.EditorFor(person => person.Age) %><br />
        <% foreach (String FavoriteFoods in Model.FavoriteFoods) { %>
            <%= Html.LabelFor(food => FavoriteFoods) %><br />
            <%= Html.EditorFor(food => FavoriteFoods)%><br />
        <% } %>
        <%= Html.EditorFor(person => person.Birthday, "TwoPart") %>
        <input type="submit" value="Submit" />
    <% } %>

</asp:Content>

यहां बाल वर्ग के लिए दृढ़ता से टाइप किया गया दृश्य है (जिसे संपादक टेम्पलेट्स नामक दृश्य निर्देशिका के सबफ़ोल्डर में संग्रहीत किया जाना चाहिए):

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MvcLearner.Models.TwoPart>" %>

<%= Html.LabelFor(birthday => birthday.Day) %><br />
<%= Html.EditorFor(birthday => birthday.Day) %><br />

<%= Html.LabelFor(birthday => birthday.Month) %><br />
<%= Html.EditorFor(birthday => birthday.Month) %><br />

नियंत्रक यहां है:

public class PersonController : Controller
{
    //
    // GET: /Person/
    [AcceptVerbs(HttpVerbs.Get)]
    public ActionResult Index()
    {
        return View();
    }

    [AcceptVerbs(HttpVerbs.Get)]
    public ActionResult Create()
    {
        Person person = new Person();
        person.FavoriteFoods.Add("Sushi");
        return View(person);
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Create(Person person)
    {
        return View(person);
    }
}

यहां कस्टम कक्षाएं दी गई हैं:

public class Person
{
    public String Name { get; set; }
    public Int32 Age { get; set; }
    public List<String> FavoriteFoods { get; set; }
    public TwoPart Birthday { get; set; }

    public Person()
    {
        this.FavoriteFoods = new List<String>();
        this.Birthday = new TwoPart();
    }
}

public class TwoPart
{
    public Int32 Day { get; set; }
    public Int32 Month { get; set; }
}

और आउटपुट स्रोत:

<form action="/Person/Create" method="post"><label for="Name">Name</label><br /> 
    <input class="text-box single-line" id="Name" name="Name" type="text" value="" /><br /> 
    <label for="Age">Age</label><br /> 
    <input class="text-box single-line" id="Age" name="Age" type="text" value="0" /><br /> 
    <label for="FavoriteFoods">FavoriteFoods</label><br /> 
    <input class="text-box single-line" id="FavoriteFoods" name="FavoriteFoods" type="text" value="Sushi" /><br /> 
    <label for="Birthday_Day">Day</label><br /> 
    <input class="text-box single-line" id="Birthday_Day" name="Birthday.Day" type="text" value="0" /><br /> 

    <label for="Birthday_Month">Month</label><br /> 
    <input class="text-box single-line" id="Birthday_Month" name="Birthday.Month" type="text" value="0" /><br /> 
    <input type="submit" value="Submit" /> 
</form>

अब यह पूरा हो गया है। सत्यापित करने के लिए पोस्ट पोस्ट नियंत्रक कार्रवाई में ब्रेकपॉइंट सेट करें। सूचियों के साथ इसका उपयोग न करें क्योंकि यह काम नहीं करेगा। उस पर अधिक जानकारी के लिए INumerable के साथ EditorTemplates का उपयोग करने पर मेरा प्रश्न देखें।


मैं इस मुद्दे पर भी आया और बहुत दर्द के बाद मुझे पता चला कि मेरे इंटरफेस को फिर से डिजाइन करना आसान था जैसे कि मुझे नेस्टेड मॉडल ऑब्जेक्ट्स को पोस्ट करने की आवश्यकता नहीं थी। इसने मुझे अपने इंटरफेस वर्कफ़्लोज़ को बदलने के लिए मजबूर कर दिया: यकीन है कि अब मुझे उपयोगकर्ता को दो चरणों में करने की आवश्यकता है जो मैंने एक पर करने का सपना देखा है, लेकिन नए दृष्टिकोण की उपयोगिता और कोड रखरखाव अब मेरे लिए अधिक मूल्यवान है।

उम्मीद है कि यह कुछ मदद करता है।


अगर किसी को इसकी आवश्यकता हो तो एएसपीनेट कोर 2 के लिए PartailFor

    public static ModelExplorer GetModelExplorer<TModel, TResult>(this IHtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TResult>> expression)
    {
        if (expression == null)
            throw new ArgumentNullException(nameof(expression));
        return ExpressionMetadataProvider.FromLambdaExpression(expression, htmlHelper.ViewData, htmlHelper.MetadataProvider);
    }

    public static IHtmlContent PartialFor<TModel, TResult>(this IHtmlHelper<TModel> helper, Expression<Func<TModel, TResult>> expression, string partialViewName, string prefix = "")
    {
        var modelExplorer = helper.GetModelExplorer(expression);
        helper.ViewData.TemplateInfo.HtmlFieldPrefix += prefix;
        return helper.Partial(partialViewName, modelExplorer.Model, helper.ViewData);
    }

आप की तरह, मैं अपने व्यूमोडल्स में प्रीफिक्स प्रॉपर्टी (एक स्ट्रिंग) जोड़ता हूं जिसे मैं अपने मॉडल बाध्य इनपुट नाम से पहले जोड़ता हूं। (YAGNI नीचे को रोकने)

एक अधिक सुरुचिपूर्ण समाधान बेस व्यू मॉडल हो सकता है जिसमें इस संपत्ति और कुछ HtmlHelpers हैं जो जांचते हैं कि दृश्य मॉडल इस आधार से निकला है और यदि ऐसा है तो उपसर्ग इनपुट नाम में संलग्न करें।

उम्मीद है की वो मदद करदे,

सज्जन


आप रेंडरपार्टियल को कॉल करने से ठीक पहले कैसे करते हैं

<% ViewData["Prefix"] = "Child."; %>
<% Html.RenderPartial("AnotherViewModelControl", Model.Child) %>

फिर आपके आंशिक में आपके पास है

<%= Html.TextBox(ViewData["Prefix"] + "Name", Model.Name) %>




mvccontrib