मुझे एएसपी.नेट एमवीसी 3 एप्लिकेशन में मेरे रेज़र विचारों में से एक के साथ एक अजीब समस्या है। मुझे यह बताते हुए एक त्रुटि मिल रही है कि एक संपत्ति नहीं मिल सकती है, जब संपत्ति डीबगर कंसोल के लिए अपना मूल्य लिखते समय मौजूद प्रतीत होती है।एएसपी.नेट एमवीसी 3 में रेजर और इंटरफेस विरासत: यह संपत्ति क्यों नहीं मिल सकती है?
मेरा विचार फॉर्म मॉडल के रूप में फॉर्म नामित करता है जिसे FormEditViewModel कहा जाता है। FormEditViewModel में IForm टाइप की एक संपत्ति है, एक इंटरफ़ेस जो किसी अन्य इंटरफ़ेस से प्राप्त होता है, IFormObject। IFormObject एक संपत्ति नाम परिभाषित करता है, इसलिए IForm को लागू करने वाले किसी भी नाम को नाम की एक संपत्ति को कार्यान्वित करना होगा। कंक्रीट प्रकार प्रपत्र इंटरफ़ेस IForm लागू करता है और आवश्यकतानुसार नाम संपत्ति को परिभाषित करता है।
जब मैं कोड चलाता हूं और व्यू को पास किए गए FormEditViewModel ऑब्जेक्ट का निरीक्षण करता हूं, तो मैं देख सकता हूं कि इसमें एक संपत्ति प्रपत्र है, प्रकार IForm है, और इस फ़ॉर्म ऑब्जेक्ट में नाम संपत्ति है। फिर भी जब मैं दृश्य मैं चलाने
Debug.WriteLine("Name: " + vm.Form.Name);
: अगर मैं अपने नियंत्रक में निम्न पंक्ति डालें, बस से पहले ही दृश्य में पारित हो जाता है FormEditViewModel.Name का मूल्य को लिखने के लिए, उत्पादन खिड़की सही नाम से पता चलता एक त्रुटि कह रही है कि "संपत्ति MyCompany.MyAplication.Domain.Forms.IForm.Name नहीं मिला।" नियंत्रक में सी # कोड स्पष्ट रूप से क्यों कर सकता है जब रेजर नाम संपत्ति नहीं ढूंढ सकता है?
मेरा विचार इस तरह है। अपवाद फेंकने वाली रेखा @ Html.LabelFor (मॉडल => model.Form.Name, "फॉर्म शीर्षक") है।
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using MyCompany.MyApplication.Domain.Forms;
using MyCompany.App.Web.ViewModels;
namespace MyCompany.MyApplication.ViewModels
{
public class FormEditViewModel : ViewModelBase
{
public IForm Form { get; set; }
public int Id
{
get { return Form.ZooFormId; }
}
public IEnumerable<Type> Types { get; set; }
public Dictionary<string, string> FriendlyNamesForTypes { get; set; }
public Dictionary<string, string> FriendlyNamesForProperties { get; set; }
public IEnumerable<String> PropertiesForUseInForms { get; set; }
public ObjectBrowserTreeViewModel ObjectBrowserTreeViewModel { get; set; }
}
}
फार्म वस्तु वास्तव में लंबा है, इसलिए मैं यहाँ में पूरी बात पेस्ट नहीं होगा:
@using MyCompany.MyApplication.ViewModels;
@model FormEditViewModel
@{
ViewBag.Title = "Edit form";
}
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<div class="MyApplicationcontainer">
@using (Html.BeginForm("UpdateForm", "ZooForm"))
{
<div class="formHeader">
@Html.ValidationSummary(true)
@Html.Hidden("id", Model.Form.ZooFormId)
<div id="editFormTitleDiv">
<div class="formFieldContainer">
@Html.Label("Form ID")
@Html.TextBoxFor(m => m.Form.ZooFormId, new { @disabled = true })
</div>
<div class="formFieldContainer">
@Html.LabelFor(model => model.Form.Name, "Form title")
@Html.EditorFor(model => model.Form.Name)
@Html.ValidationMessageFor(model => model.Form.Name)
</div>
...
यहाँ दृश्य मॉडल है। यह इस तरह से घोषित किया जाता है:
public class Form : FormObject, IForm
फार्म वस्तु का नाम संपत्ति को फिर से परिभाषित नहीं करता, लेकिन FormObject वर्ग से इनहेरिट करती है। FormObject इस तरह शुरू होता है:
public abstract class FormObject : IFormObject
यहां इंटरफ़ेस iform है। आप देख सकते हैं, यह एक नाम सदस्य की घोषणा नहीं करता है, लेकिन वारिस है कि IFormObject से उम्मीद:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MyCompany.MyApplication.Domain.Forms
{
public interface IFormObject
{
string Name { get; }
string LongName { get; }
Guid UniqueId { get; }
string Prefix { get; }
string IdPath { get; set; }
string IdPathWithPrefix { get; }
}
}
सवाल है, क्यों उस्तरा करता है:
using System;
namespace MyCompany.MyApplication.Domain.Forms
{
public interface IForm : IFormObject
{
bool ContainsRequiredFields();
MyCompany.MyApplication.Domain.Forms.Factories.IFormFieldFactory FormFieldFactory { get; }
MyCompany.MyApplication.Domain.Forms.Factories.IFormPageFactory FormPageFactory { get; }
string FriendlyName { get; set; }
System.Collections.Generic.List<IFormField> GetAllFields();
System.Collections.Generic.IEnumerable<DomainObjectPlaceholder> GetObjectPlaceholders();
System.Collections.Generic.IEnumerable<IFormField> GetRequiredFields();
System.Collections.Generic.IEnumerable<MyCompany.MyApplication.Models.Forms.FormObjectPlaceholder> GetRequiredObjectPlaceholders();
System.Collections.Generic.List<IFormSection> GetSectionsWithMultipliableOption();
MyCompany.MyApplication.BLL.IHighLevelFormUtilities HighLevelFormUtilities { get; }
int? MasterId { get; set; }
DomainObjectPlaceholder MasterObjectPlaceholder { get; set; }
MyCompany.MyApplication.Domain.Forms.Adapters.IObjectPlaceholderAdapter ObjectPlaceholderAdapter { get; }
MyCompany.MyApplication.Domain.Forms.Adapters.IObjectPlaceholderRelationshipAdapter ObjectPlaceholderRelationshipAdapter { get; }
System.Collections.Generic.List<IFormPage> Pages { get; set; }
MyCompany.MyApplication.Repository.IAppRepository AppRepo { get; set; }
int ZooFormId { get; }
MyCompany.MyApplication.BLL.IPocoUtils PocoUtils { get; }
void RemoveSectionWithoutChangingDatabase(int sectionId);
int? TopicId { get; set; }
DomainObjectPlaceholder TopicObjectPlaceholder { get; set; }
System.Collections.Generic.IEnumerable<FluentValidation.Results.ValidationResult> ValidationResults { get; set; }
}
}
और यहाँ इंटरफेस IFormObject है जब मैं इसे चलाता हूं तो मुझे निम्नलिखित अपवाद दें, क्योंकि मुझे उम्मीद है कि IForm IFormObject से इसकी नाम संपत्ति का उत्तराधिकारी होगा?
Server Error in '/' Application.
The property MyCompany.MyApplication.Domain.Forms.IForm.Name could not be found.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.ArgumentException: The property MyCompany.MyApplication.Domain.Forms.IForm.Name could not be found.
Source Error:
Line 24: </div>
Line 25: <div class="formFieldContainer">
Line 26: @Html.LabelFor(model => model.Form.Name, "Form title")
Line 27: @Html.EditorFor(model => model.Form.Name)
Line 28: @Html.ValidationMessageFor(model => model.Form.Name)
Source File: c:\Users\me\Documents\Visual Studio 2010\Projects\zooDBMain\zooDB\zooDB\Views\ZooForm\Edit.cshtml Line: 26
Stack Trace:
[ArgumentException: The property MyCompany.MyApplication.Domain.Forms.IForm.Name could not be found.]
System.Web.Mvc.AssociatedMetadataProvider.GetMetadataForProperty(Func`1 modelAccessor, Type containerType, String propertyName) +505385
System.Web.Mvc.ModelMetadata.GetMetadataFromProvider(Func`1 modelAccessor, Type modelType, String propertyName, Type containerType) +101
System.Web.Mvc.ModelMetadata.FromLambdaExpression(Expression`1 expression, ViewDataDictionary`1 viewData) +421
System.Web.Mvc.Html.LabelExtensions.LabelFor(HtmlHelper`1 html, Expression`1 expression, String labelText) +56
ASP._Page_Views_ZooForm_Edit_cshtml.Execute() in c:\Users\me\Documents\Visual Studio 2010\Projects\zooDBMain\zooDB\zooDB\Views\ZooForm\Edit.cshtml:26
System.Web.WebPages.WebPageBase.ExecutePageHierarchy() +272
System.Web.Mvc.WebViewPage.ExecutePageHierarchy() +81
System.Web.WebPages.StartPage.RunPage() +58
System.Web.WebPages.StartPage.ExecutePageHierarchy() +94
System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage) +173
System.Web.Mvc.RazorView.RenderView(ViewContext viewContext, TextWriter writer, Object instance) +220
System.Web.Mvc.BuildManagerCompiledView.Render(ViewContext viewContext, TextWriter writer) +115
System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context) +303
System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult) +13
System.Web.Mvc.<>c__DisplayClass1c.<InvokeActionResultWithFilters>b__19() +23
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation) +260
System.Web.Mvc.<>c__DisplayClass1e.<InvokeActionResultWithFilters>b__1b() +19
System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult) +177
System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +343
System.Web.Mvc.Controller.ExecuteCore() +116
System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) +97
System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) +10
System.Web.Mvc.<>c__DisplayClassb.<BeginProcessRequest>b__5() +37
System.Web.Mvc.Async.<>c__DisplayClass1.<MakeVoidDelegate>b__0() +21
System.Web.Mvc.Async.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _) +12
System.Web.Mvc.Async.WrappedAsyncResult`1.End() +62
System.Web.Mvc.<>c__DisplayClasse.<EndProcessRequest>b__d() +50
System.Web.Mvc.SecurityUtil.<GetCallInAppTrustThunk>b__0(Action f) +7
System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action) +22
System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +60
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8971485
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +184
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.547
मुझे खुशी है कि मेरे वंशानुगत पदानुक्रम थोड़ा गंदा है और यह सबसे सुंदर कोड नहीं है, लेकिन मुझे पता है कि ऐसा क्यों होता है और क्या मेरे विकल्प यह तय करने के लिए कर रहे हैं उत्सुक हूँ। क्या मैं सी # में इंटरफेस विरासत कैसे काम करता है इस बारे में कुछ समझने में असफल रहा हूं?
धन्यवाद ब्रायन।माइक्रोसॉफ्ट को यह तय करने का कोई इरादा नहीं है कि इसे ठीक करने का कोई इरादा नहीं है और (आपके लिंक के पहले स्कॉट हंसेलमैन की टिप्पणी से) कि "इंटरफ़ेस-आधारित मॉडल होने से हम कुछ भी प्रोत्साहित नहीं करते हैं।" चूंकि सिद्धांत रूप से किसी भी वर्ग को एक दृश्य के माध्यम से पारित किया जा सकता है, जिसमें सदस्यों के साथ एक ठोस वर्ग शामिल है, जिसका प्रकार एक इंटरफ़ेस है (जैसा कि मेरे मामले में है) उनकी सलाह वास्तव में सुरक्षित पक्ष पर होने के लिए पूरी तरह से इंटरफेस से परहेज करती है, जो खराब अभ्यास की तरह लगती है । मैं आपके वर्कअराउंड का उपयोग करूंगा, जिसे पढ़ना चाहिए: @ एचटीएमएल। हिडनफ़ोर (एम => (एमफॉर्मऑब्जेक्ट के रूप में एम)। नाम) – Richard
@ रिचर्ड: ठीक है अब एएसपी.नेट एमवीसी ओपन-सोर्स है, चीजें बदल सकती हैं :) –