टेरी मेरे दोस्त, तुम और मुझे एक ड्रिंक चाहिए। हमारी कुछ ऐसी ही समस्याएं हैं।
1. प्रोजेक्ट संरचना: मैं एडुआर्डो से सहमत हूं कि एमवीसी ऐप में फ़ोल्डर संरचना वांछित होने के लिए कुछ छोड़ देता है। आपके पास अपने मानक नियंत्रक, मॉडल और दृश्य फ़ोल्डर हैं। लेकिन तब व्यू फ़ोल्डर प्रत्येक नियंत्रक, और एक साझा फ़ोल्डर के लिए एक अलग फ़ोल्डर में टूट जाता है। और प्रत्येक दृश्य / नियंत्रकनाम या दृश्य / साझा को EditorTemplates और DisplayTemplates में तोड़ा जा सकता है। लेकिन यह आपको अपने मॉडल फ़ोल्डर को व्यवस्थित करने का निर्णय लेने देता है (आप सबफ़ोल्डर्स और अतिरिक्त नेमस्पेस घोषणाओं के साथ या बिना कर सकते हैं)।
भगवान न करें कि आप ऐसे क्षेत्रों का उपयोग कर रहे हैं, जो प्रत्येक क्षेत्र के नियंत्रक, मॉडल और दृश्य फ़ोल्डर संरचना की नकल करते हैं।
/Areas
/Area1Name
/Controllers
FirstController.cs
SecondController.cs
ThirdController.cs
/Models
(can organize all in here or in separate folders / namespaces)
/Views
/First
/DisplayTemplates
WidgetAbc.cshtml <-- to be used by views in Views/First
/EditorTemplates
WidgetAbc.cshtml <-- to be used by views in Views/First
PartialViewAbc.cshtml <-- to be used by FirstController
/Second
PartialViewDef.cshtml <-- to be used by SecondController
/Third
PartialViewMno.cshtml <-- to be used by ThirdController
/Shared
/DisplayTemplates
WidgetXyz.cshtml <-- to be used by any view in Area1
/EditorTemplates
WidgetXyz.cshtml <-- to be used by any view in Area1
PartialViewXyz.cshtml <-- to be used anywhere in Area1
_ViewStart.cshtml <-- area needs its own _ViewStart.cshtml
Web.config <-- put custom HTML Helper namespaces in here
Area1NameRegistration.cs <-- define routes for area1 here
/Area2Name
/Controllers
/Models
/Views
Area2NameRegistration.cs <-- define routes for area2 here
/Controllers
AccountController.cs
HomeController.cs
/Models
/Views
/Account
/DisplayTemplates
WidgetGhi.cshtml <-- to be used views in Views/Account
/EditorTemplates
WidgetGhi.cshtml <-- to be used views in Views/Account
PartialViewGhi.cshtml <-- to be used by AccountController
/Home
(same pattern as Account, views & templates are controller-specific)
/Shared
/DisplayTemplates
EmailAddress.cshtml <-- to be used by any view in any area
Time.cshtml <-- to be used by any view in any area
Url.cshtml <-- to be used by any view in any area
/EditorTemplates
EmailAddress.cshtml <-- to be used by any view in any area
Time.cshtml <-- to be used by any view in any area
Url.cshtml <-- to be used by any view in any area
_Layout.cshtml <-- master layout page with sections
Error.cshtml <-- custom page to show if unhandled exception occurs
_ViewStart.cshtml <-- won't be used automatically in an area
Web.config <-- put custom HTML Helper namespaces in here
इसका मतलब है कि यदि आप किसी विजेट-कंट्रोलर जैसी किसी चीज के साथ काम कर रहे हैं, तो आपको संबंधित WidgetViewModels, WidgetViews, WidgetEditorTemplates, WidgetDisplayTemplates, आदि को खोजने के लिए अन्य फ़ोल्डरों में देखना होगा। जैसा कि यह बोझिल हो सकता है, मैं इससे चिपक जाता हूं और इससे विचलित नहीं होता हूं। ये एमवीसी सम्मेलन। जहाँ तक एक ही फ़ोल्डर में एक मॉडल, नियंत्रक, और दृश्य डालने की बात है, लेकिन विभिन्न नामस्थानों के साथ, मैं इससे बचता हूं क्योंकि मैं ReSharper का उपयोग करता हूं। यह स्क्विग्ली को एक नेमस्पेस को रेखांकित करेगा जो उस फ़ोल्डर से मेल नहीं खाता जहां क्लास स्थित है। मुझे पता है कि मैं इस R # सुविधा को बंद कर सकता हूं, लेकिन यह परियोजना के अन्य हिस्सों में मदद करता है।
गैर-श्रेणी की फ़ाइलों के लिए, MVC आपको बॉक्स से सामग्री और लिपियाँ देता है। हम अपने सभी स्थिर / गैर-संकलित फ़ाइलों को इन स्थानों में रखने की कोशिश करते हैं, फिर से, सम्मेलन का पालन करने के लिए। किसी भी समय हम एक js लाइब्रेरी को शामिल करते हैं जो थीम (चित्र और या सीएसएस) का उपयोग करता है, थीम फ़ाइलें सभी / सामग्री के तहत कहीं जाती हैं। स्क्रिप्ट के लिए, हम सीधे उन सभी को सीधे / स्क्रिप्ट में डालते हैं। मूल रूप से यह वीएस से जेएस इंटेलीसेन्स पाने के लिए था, लेकिन अब जब हम आर # से जेएस इंटैलिजेंस प्राप्त करते हैं, तो / इन लिपियों में प्लेसमेंट की परवाह किए बिना, मुझे लगता है कि हम इससे विचलित हो सकते हैं और स्क्रिप्ट को बेहतर व्यवस्थित करने के लिए फ़ोल्डर से विभाजित कर सकते हैं। क्या आप ReSharper का उपयोग कर रहे हैं? यह शुद्ध सोने का IMO है।
सोने का एक और छोटा टुकड़ा जो रिफैक्टरिंग में बहुत मदद करता है वह है T4MVC। इसका उपयोग करते हुए, हमें क्षेत्र के नाम, नियंत्रक नाम, कार्रवाई नाम, यहां तक कि सामग्री और स्क्रिप्ट में फ़ाइलों के लिए स्ट्रिंग पथ में टाइप करने की आवश्यकता नहीं है। T4MVC दृढ़ता से आप के लिए सभी जादुई तार टाइप करता है। यहाँ एक छोटा सा नमूना है कि कैसे आपकी परियोजना संरचना उतनी मायने नहीं रखती है अगर आप T4MVC का उपयोग कर रहे हैं:
// no more magic strings in route definitions
context.MapRoutes(null,
new[] { string.Empty, "features", "features/{version}" },
new
{
area = MVC.PreviewArea.Name,
controller = MVC.PreviewArea.Features.Name,
action = MVC.PreviewArea.Features.ActionNames.ForPreview,
version = "december-2011-preview-1",
},
new { httpMethod = new HttpMethodConstraint("GET") }
);
@* T4MVC renders .min.js script versions when project is targeted for release *@
<link href="@Url.Content(Links.content.Site_css)?r=201112B" rel="stylesheet" />
<script src="@Url.Content(Links.scripts.jquery_1_7_1_js)" type="text/javascript">
</script>
@* render a route URL as if you were calling an action method directly *@
<a href="@Url.Action(MVC.MyAreaName.MyControllerName.MyActionName
(Model.SomeId))">@Html.DisplayFor(m => m.SomeText)</a>
// call action redirects as if you were executing an action method
return RedirectToAction(MVC.Area.MyController.DoSomething(obj1.Prop, null));
2. डेटा का उपयोग: मुझे पेटाको के साथ कोई अनुभव नहीं है, लेकिन मुझे यकीन है कि यह जांचने लायक है। आपकी जटिल रिपोर्टों के लिए, क्या आपने SQL सर्वर रिपोर्टिंग सेवाओं पर विचार किया है? या, आप एक अलग db पर चल रहे हैं? क्षमा करें, आप जो पूछ रहे हैं, मैं उस पर स्पष्ट नहीं हूं। हम EF + LINQ का उपयोग करते हैं, लेकिन डोमेन कक्षाओं में रिपोर्ट कैसे उत्पन्न करते हैं, इसके बारे में भी हम कुछ ज्ञान रखते हैं। इस प्रकार, हमारे पास नियंत्रक कॉल डोमेन सेवा कॉल रिपॉजिटरी है, इसके बजाय सीधे नियंत्रक कॉल रिपॉजिटरी है। तदर्थ रिपोर्टों के लिए हम SQL रिपोर्टिंग सेवा का उपयोग करते हैं, जो फिर से सही नहीं है, लेकिन हमारे उपयोगकर्ता आसानी से एक्सेल में डेटा लाने में सक्षम होना पसंद करते हैं, और SSRS उस पर हमें आसान बनाता है।
3. क्लाइंट-साइड कोड संगठन और यूआई प्रतिपादन: यह वह जगह है जहां मुझे लगता है कि मैं कुछ मदद की पेशकश करने में सक्षम हो सकता हूं। MVC विनीत सत्यापन और विनीत AJAX की पुस्तक से एक पृष्ठ लें। इस पर विचार करो:
<img id="loading_spinner" src="/path/to/img" style="display:none;" />
<h2 id="loading_results" style="display:none;">
Please wait, this may take a while...
</h2>
<div id="results">
</div>
<input id="doSomethingDangerous" class="u-std-ajax"
type="button" value="I'm feeling lucky"
data-myapp-confirm="Are you sure you want to do this?"
data-myapp-show="loading_spinner,loading_results"
data-myapp-href="blah/DoDangerousThing" />
अब (इस पर बाद में) के लिए ajax सफलता समारोह पर ध्यान न दें। आप अपने कुछ कार्यों के लिए एक स्क्रिप्ट के साथ भाग सकते हैं:
$('.u-std-ajax').click(function () {
// maybe confirm something first
var clicked = this;
var confirmMessage = $(clicked).data('myapp-confirm');
if (confirmMessage && !confirm(confirmMessage )) { return; }
// show a spinner? something global would be preferred so
// I dont have to repeat this on every page
// maybe the page should notify the user of what's going on
// in addition to the dialog?
var show = $(clicked).data('myapp-show');
if (show) {
var i, showIds = show.split(',');
for (i = 0; i < showIds.length; i++) {
$('#' + showIds[i]).show();
}
}
var url = $(clicked).data('myapp-href');
if (url) {
$.ajax({
url: url,
complete: function () {
// Need to hide the spinner, again would prefer to
// have this done elsewhere
if (show) {
for (i = 0; i < showIds.length; i++) {
$('#' + showIds[i]).hide();
}
}
}
});
}
});
उपरोक्त कोड पुष्टि की देखभाल करेगा, स्पिनर को दिखाना, प्रतीक्षा संदेश दिखाना, और अजाक्स कॉल पूरा होने के बाद स्पिनर / प्रतीक्षा संदेश को छिपाना। आप डेटा का उपयोग करके व्यवहार को कॉन्फ़िगर करते हैं- * विशेषताएँ, विनीत पुस्तकालयों की तरह।
सामान्य सवाल
- क्लाइंट MVC बनाम सर्वर MVC? मैंने सफलता के कार्य में आपके द्वारा की गई कार्रवाइयों को लाइब्रेरियलाइज करने की कोशिश नहीं की क्योंकि ऐसा लगता है कि आपका कंट्रोलर JSON लौटा रहा है। यदि आपके नियंत्रक JSON लौटा रहे हैं, तो आप KnockoutJS को देखना चाहते हैं। नॉकआउट जेएस संस्करण 2.0 आज जारी किया गया था । यह आपके JSON में सही प्लग-इन कर सकता है, ताकि एक देखने योग्य क्लिक स्वचालित रूप से आपके जावास्क्रिप्ट टेम्प्लेट में डेटा को बाँध सके। दूसरी ओर, यदि आपको अपने ऐजैक्स एक्शन के तरीकों से एतराज नहीं है, तो JSON के बजाय HTML को लौटाएं, वे अपने LI बच्चों के साथ पहले से निर्मित UL को वापस कर सकते हैं, और आप डेटा-myapp-response = का उपयोग करके किसी तत्व में संलग्न कर सकते हैं "परिणाम"। आपका सफलता समारोह तब बस इस तरह दिखेगा:
success: function(html) {
var responseId = $(clicked).data('myapp-response');
if (responseId) {
$('#' + responseId).empty().html(html);
}
}
इसके लिए मेरा सबसे अच्छा जवाब देने के लिए, यदि आपको JSON को अपने एक्शन तरीकों से वापस करना होगा, तो आप सर्वर-साइड व्यू को स्किप कर रहे हैं, इसलिए यह वास्तव में सर्वर MVC नहीं है - यह सिर्फ MC है। यदि आप आंशिक रूप से html.jult कॉल करने के लिए html के साथ लौटते हैं, तो यह सर्वर MVC है। तो अगर आपके ऐप को अजाक्स कॉल के लिए JSON डेटा वापस करना होगा, तो क्लाइंट MVVM जैसे KnockoutJS का उपयोग करें।
किसी भी तरह से, मुझे आपके द्वारा पोस्ट किया गया JS पसंद नहीं है क्योंकि यह आपके लेआउट (html टैग) को व्यवहार (अतुल्यकालिक डेटा लोड) के साथ मिलाता है। आंशिक JSON व्यूयूमल डेटा के साथ आंशिक HTML विचारों या क्लाइंट MVVM के साथ सर्वर MVC चुनना आपके लिए इस समस्या को हल करेगा, लेकिन मैन्युअल रूप से जावास्क्रिप्ट में DOM / HTML का निर्माण चिंताओं के पृथक्करण का उल्लंघन करता है।
- जावास्क्रिप्ट फ़ाइल निर्माण जाहिरा तौर पर minification विशेषताएँ .NET 4.5 में आ रही हैं । यदि आप विनीत मार्ग पर जाते हैं, तो आपको अपने सभी JS को 1 स्क्रिप्ट फ़ाइल में लोड करने से रोकना नहीं चाहिए। मैं प्रत्येक इकाई प्रकार के लिए अलग-अलग JS फाइलें बनाने के बारे में सावधान रहूंगा, आप JS फाइल विस्फोट के साथ समाप्त हो जाएंगे। याद रखें, आपकी स्क्रिप्ट फ़ाइल लोड होने के बाद, ब्राउज़र को इसे भविष्य के अनुरोधों के लिए कैश करना चाहिए।
- जटिल प्रश्नों को मैं जटिल होने के नाते पेजिंग, छँटाई, आदि जैसी सुविधा नहीं मानता। मेरी प्राथमिकता URL के और सर्वर-साइड तर्क के साथ इसे संभालना है, ताकि db प्रश्नों को आवश्यकतानुसार सीमित किया जा सके। हालाँकि हम Azure पर तैनात हैं, इसलिए क्वेरी ऑप्टिमाइज़ेशन हमारे लिए महत्वपूर्ण है। उदाहरण के लिए /widgets/show-{pageSize}-per-page/page-{pageNumber}/sort-by-{sortColumn}-{sortDirection}/{keyword}
:। EF और LINQ से लेकर एंटिटीज, जैसे कि .Take (), .Skk (), .OrderBy (), और .OderByDescending () जैसे तरीकों से पेजिंग और सॉर्टिंग को हैंडल कर सकते हैं, इसलिए आपको db ट्रिप के दौरान क्या चाहिए। मुझे अभी तक एक ग्राहक की जरूरत नहीं मिली है, इसलिए मैं ईमानदारी से उनके बारे में ज्यादा नहीं जानता। उस पर अधिक सलाह के लिए अन्य उत्तरों को देखें।
- प्रोजेक्ट सिल्क इस बारे में कभी नहीं सुना, इसे जांचना होगा। मैं स्टीव सैंडरसन, उनकी किताबों, उनकी बिगुलकेशन इटेम एचटीएमएल हेल्पर और उनके ब्लॉग का बहुत बड़ा प्रशंसक हूं। कहा कि, मुझे उत्पादन में नॉकआउट के साथ कोई अनुभव नहीं है । मैंने इसके ट्यूटोरियल की जाँच की है, लेकिन मैं कम से कम संस्करण 2.0 तक कुछ करने की कोशिश नहीं कर रहा हूँ। जैसा कि मैंने उल्लेख किया, नॉकआउट जेएस 2.0 अभी जारी किया गया था।
- एन-टीयर यदि टियर द्वारा आपका मतलब अलग-अलग भौतिक मशीन से है, तो नहीं, मुझे नहीं लगता कि कुछ भी किसी भी विंडोज़ से बाहर जाता है। आम तौर पर 3-स्तरीय का मतलब है कि आपके पास 3 मशीनें हैं। तो आपकी प्रस्तुति के रूप में आपके पास एक मोटा ग्राहक हो सकता है, जो उपयोगकर्ता की मशीन पर चलता है। वसा ग्राहक एक सेवा स्तरीय का उपयोग कर सकता है, जो एक एप्लिकेशन सर्वर पर चलता है और एक्सएमएल या जो भी वसा ग्राहक को देता है। और सर्विस टियर को SQL सर्वर से 3rd मशीन पर अपना डेटा मिल सकता है।
1 स्तरीय पर MVC एक परत है। आपके नियंत्रक, मॉडल और विचार सभी आपकी प्रस्तुति परत का हिस्सा हैं, जो भौतिक वास्तुकला में 1 स्तरीय है। एमवीसी मॉडल-व्यू-कंट्रोलर पैटर्न को लागू करता है, जो कि आपको अतिरिक्त परतें दिखाई दे रही है। हालाँकि, इन 3 पहलुओं को टियर या लेयर के रूप में नहीं समझने की कोशिश करें। इन तीनों को प्रेजेंटेशन लेयर कंसर्न के रूप में सोचने की कोशिश करें।
अध्यक्ष / बस / डेटा टिप्पणी के बाद अपडेट करें
ठीक है, इसलिए आप टियर और लेयर को एक-दूसरे से अलग-अलग तरीके से इस्तेमाल कर रहे हैं। मैं आमतौर पर तार्किक / प्रोजेक्ट / असेंबली डिवीजनों के लिए "लेयर" शब्द का उपयोग करता हूं, और भौतिक नेटवर्क पृथक्करण के लिए स्तरीय हूं। गलतफहमी के लिए खेद है।
आपको एमवीसी शिविर में काफी लोग मिलेंगे, जो कहते हैं कि आपको अपने इकाई डेटा मॉडल के लिए एमवीसी में "मॉडल" का उपयोग नहीं करना चाहिए, और न ही आपको व्यापार तर्क के लिए अपने नियंत्रकों का उपयोग करना चाहिए। आदर्श रूप से आपके मॉडल दृश्य-विशिष्ट दृश्यमॉडल होने चाहिए। आटोमैपर जैसी किसी चीज़ का उपयोग करते हुए, आप अपने डोमेन मॉडल से अपनी संस्थाओं को लेते हैं और उन्हें ViewModels में डीटीओ करते हैं, विशेष रूप से दृश्य द्वारा उपयोग के लिए खोदे गए।
कोई भी व्यावसायिक नियम आपके डोमेन का हिस्सा होना चाहिए, और आप उन्हें डोमेन सेवाओं / फ़ैक्टरी पैटर्न का उपयोग करके लागू कर सकते हैं / जो आपके डोमेन परत में उपयुक्त है, एमवीसी प्रस्तुति परत में नहीं। नियंत्रकों को गूंगा होना चाहिए, हालांकि मॉडल के रूप में बहुत गूंगा नहीं है, और व्यवसाय ज्ञान की आवश्यकता वाले किसी भी चीज़ के लिए डोमेन को जिम्मेदारी देनी चाहिए। कंट्रोलर HTTP अनुरोधों और प्रतिक्रियाओं के प्रवाह का प्रबंधन करते हैं, लेकिन वास्तविक व्यापार मूल्य के साथ कुछ भी नियंत्रक के वेतन ग्रेड से ऊपर होना चाहिए।
तो, आप अभी भी एक स्तरित वास्तुकला हो सकते हैं, एमवीसी के साथ प्रस्तुति परत के रूप में। यह आपके एप्लिकेशन लेयर, सर्विस लेयर, या डोमेन लेयर का एक क्लाइंट है, यह इस बात पर निर्भर करता है कि आप इसे कैसे आर्किटेक्ट करते हैं। लेकिन अंततः आपका इकाई मॉडल डोमेन का हिस्सा होना चाहिए, न कि एमवीसी में मॉडल।