سؤال

ولقد شاهدت العديد من الأسئلة حول هذا الموضوع، ولكني لم يحصل حقا الإجابة التي أحتاج.

وأنا تحويل تطبيق ويب كبير إلى حد ما من أشكال ويب لMVC وبعد فترة من الوقت كنت encountred مشكلة مع بيانات مرور إلى طريقة العرض. في العمل I تنفيذ التعليمات البرمجية:

و//This is just an example ViewData["QProducts"] = from p in db.Products select new{Name = p.Name, Date = p.ToShortDateString() } ViewData["QUsers"] = from u in db.Users select u;

وأنا استخدم حلقة foreach تكرار خلال الكائنات في أتش تي أم أل، مثل هذا:

foreach(var q in (IEnumerable)ViewData["QEvents"])
{ 
    /*Print the data here*/
}

وقبل استخدام MVC كنت مجرد asp:Repeater، ولكن لأن هذا هو MVC لا يمكنني استخدام عناصر تحكم ASP.NET.

وكيف لي أن لتمرير هذه البيانات لعرض؟ ليس لدي حقا خيار عدم استخدام أنواع مجهول هنا. <%#ViewData.Eval()%> من الواضح لا تعمل.

وأي أفكار؟

هل كانت مفيدة؟

المحلول

وبدلا من نوع مجهول، وخلق نوع لعقد اسم وتاريخ:

public class NameDate
{
  public string Name { get; set; }
  public DateTime Date { get; set; }
}

وثم استخدام ذلك في الاستعلام ينق الخاص بك:

from p in db.Products select new NameDate { Name = p.Name, Date = p.Date }

وبقوة اكتب رأيك أن MyView<IEnumerable<NameDate>> ثم لا مجرد foreach ( var nameDate in ViewData.Model )...

نصائح أخرى

إذا كنت تشعر كسول قليلا، ويمكنك استخدام هذا الرمز هنا ... انها طويلة قليلا، ولكن أساسا انها المجمع للتأمل ...

var something = { Name = "Jim", Age = 25 };
AnonymousType type = AnonymousType.Create(something);

//then used...
string name = type.Get<string>("Name");
int age = type.Get<int>("Age", -1 /* optional default value */);

وهنا هو رمز ...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace Code {

    /// <summary>
    /// A convenient method of accessing the values of an 
    /// anonymous type without needing to define a separate class
    /// </summary>
    public class AnonymousType {

        #region Constants

        private const string EXCEPTION_MISSING_PARAMETER_INFORMATION = 
            "Unable to match the parameter '{0}' to a property in the AnonymousType. This could be due to a casting problem or a Property that does not exist.";
        private const string EXCEPTION_COULD_NOT_ACCESS_FIELD =
            "Unable to find a field named '{0}' (of type {1})";
        private const string EXCEPTION_COULD_NOT_ACCESS_FIELD_AT_INDEX =
            "Unable to find a field named '{0}' at the requested index (of type {1})";

        #endregion

        #region Constructors

        /// <summary>
        /// Creates a new AutoType for methods that return Anonymus types
        /// </summary>
        public AnonymousType(object type) {
            this._Init(type, false);
        }

        /// <summary>
        /// Creates a new AutoType for methods that return Anonymus types and
        /// detetrmins if exceptions should be thrown if a type is missing
        /// </summary>
        public AnonymousType(object type, bool supressErrors) {
            this._Init(type, supressErrors);
        }

        /// <summary>
        /// Initalizes the data for the is type
        /// </summary>
        private void _Init(object type, bool supressErrors) {
            this.SupressExceptions = supressErrors;
            this.m_Type = type.GetType();
            this.m_TypeData = type; 
        }

        #endregion

        #region Static Routines

        /// <summary>
        /// Creates a new Anonymous Type from the provided object data
        /// </summary>
        public static AnonymousType Create(object data) {
            return new AnonymousType(data);
        }

        /// <summary>
        /// Creates a new Anonymous Type from the provided object data
        /// </summary>
        public static AnonymousType Create(object data, bool supressErrors) {
            return new AnonymousType(data, supressErrors);
        }

        #endregion

        #region Private Members

        /// <summary>
        /// The type that will be accessed via reflection
        /// </summary>
        private Type m_Type;

        /// <summary>
        /// The actual typs that is being used
        /// </summary>
        private object m_TypeData;

        #endregion

        #region Properties

        /// <summary>
        /// Determines if errors should be thrown if any casting errors take place
        /// </summary>
        public bool SupressExceptions { get; set; }


        /// <summary>
        /// Accessess a property by name and returns an object
        /// </summary>
        public object this[string property] {
            get {
                return this.Get<object>(property);
            }
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// Checks if this Anonymous Type has the specified property
        /// </summary>
        public bool Has(string property) {
            return ((m_Type.GetProperty(property) as PropertyInfo) != null);
        }

        /// <summary>
        /// Returns if this Anonymous type has the specified property and that
        /// the value matches the type specified
        /// </summary>
        public bool Has(string property, Type isType) {

            //try and get the property
            PropertyInfo prop = m_Type.GetProperty(property) as PropertyInfo;

            //If this type doesn't exist at all, just return false
            if (prop == null) { return false; }

            //if it does exist, verify the type
            if (prop.PropertyType.Equals(isType)) { return true; }
            return false;

        }

        /// <summary>
        /// Returns a type value using the specified type
        /// </summary>
        public T Get<T>(string property) {

            //return this value if needed            
            PropertyInfo prop = m_Type.GetProperty(property) as PropertyInfo;
            try {
                return (T)prop.GetValue(this.m_TypeData, null);
            }
            catch (Exception ex) {
                if (this.SupressExceptions) { return default(T); }
                throw new Exception(
                    string.Format(EXCEPTION_COULD_NOT_ACCESS_FIELD, property, typeof(T).Name),
                    ex
                    );
            }
        }



        /// <summary>
        /// Returns a type value using the specified type
        /// </summary>
        public T Get<T>(string property, object[] index) {

            //return this value if needed
            PropertyInfo prop = m_Type.GetProperty(property) as PropertyInfo;
            try {
                return (T)prop.GetValue(this.m_TypeData, index);
            }
            catch (Exception ex) {
                if (this.SupressExceptions) { return default(T); }
                throw new Exception(
                    string.Format(EXCEPTION_COULD_NOT_ACCESS_FIELD_AT_INDEX, property, typeof(T).Name),
                    ex
                    );
            }
        }



        /// <summary>
        /// Returns a type value using the specified type but includes a default value
        /// if one it missing
        /// </summary>
        public T Get<T>(string property, T defaultValue) {
            //return this value if needed
            PropertyInfo prop = m_Type.GetProperty(property) as PropertyInfo;
            if (prop == null) { return defaultValue; }
            try {
                return (T)prop.GetValue(this.m_TypeData, null);
            }
            catch (Exception ex) {
                if (this.SupressExceptions) { return defaultValue; }
                throw new Exception(
                    string.Format(EXCEPTION_COULD_NOT_ACCESS_FIELD, prop, typeof(T).Name),
                    ex
                    );
            }

        }



        /// <summary>
        /// Accepts a delegate that will use the names of the passed in
        /// parameters as properties to map to. If the property does not
        /// exist, then the method will fail.
        /// </summary>
        public void Use<T1>(Action<T1> with) {

            //set a default for each of the params
            T1 param1 = default(T1);

            //get the parameters for this method
            var paramList = with.Method.GetParameters();

            //update each of the parameters            
            string paramName = string.Empty;
            try {
                for (int i = 0; i < paramList.Length; i++) {

                    //find the correct matching property for this parameter
                    paramName = paramList[i].Name;
                    switch (i + 1) {
                        case 1:
                            param1 = this.Get<T1>(paramName);
                            break;
                    }
                }

            }
            catch (Exception ex) {
                throw new ArgumentException(
                    string.Format(EXCEPTION_MISSING_PARAMETER_INFORMATION, paramName),
                    ex
                    );
            }

            //otherwise, execute the method provided
            with(param1);

        }



        /// <summary>
        /// Accepts a delegate that will use the names of the passed in
        /// parameters as properties to map to. If the property does not
        /// exist, then the method will fail.
        /// </summary>
        public void Use<T1, T2>(Action<T1, T2> with) {

            //set a default for each of the params
            T1 param1 = default(T1);
            T2 param2 = default(T2);

            //get the parameters for this method
            var paramList = with.Method.GetParameters();

            //update each of the parameters            
            string paramName = string.Empty;
            try {
                for (int i = 0; i < paramList.Length; i++) {

                    //find the correct matching property for this parameter
                    paramName = paramList[i].Name;
                    switch (i + 1) {
                        case 1:
                            param1 = this.Get<T1>(paramName);
                            break;

                        case 2:
                            param2 = this.Get<T2>(paramName);
                            break;
                    }
                }

            }
            catch (Exception ex) {
                throw new ArgumentException(
                    string.Format(EXCEPTION_MISSING_PARAMETER_INFORMATION, paramName),
                    ex
                    );
            }

            //otherwise, execute the method provided
            with(param1, param2);

        }



        /// <summary>
        /// Accepts a delegate that will use the names of the passed in
        /// parameters as properties to map to. If the property does not
        /// exist, then the method will fail.
        /// </summary>
        public void Use<T1, T2, T3>(Action<T1, T2, T3> with) {

            //set a default for each of the params
            T1 param1 = default(T1);
            T2 param2 = default(T2);
            T3 param3 = default(T3);

            //get the parameters for this method
            var paramList = with.Method.GetParameters();

            //update each of the parameters            
            string paramName = string.Empty;
            try {
                for (int i = 0; i < paramList.Length; i++) {

                    //find the correct matching property for this parameter
                    paramName = paramList[i].Name;
                    switch (i + 1) {
                        case 1:
                            param1 = this.Get<T1>(paramName);
                            break;

                        case 2:
                            param2 = this.Get<T2>(paramName);
                            break;

                        case 3:
                            param3 = this.Get<T3>(paramName);
                            break;
                    }
                }

            }
            catch (Exception ex) {
                throw new ArgumentException(
                    string.Format(EXCEPTION_MISSING_PARAMETER_INFORMATION, paramName),
                    ex
                    );
            }

            //otherwise, execute the method provided
            with(param1, param2, param3);

        }



        /// <summary>
        /// Accepts a delegate that will use the names of the passed in
        /// parameters as properties to map to. If the property does not
        /// exist, then the method will fail.
        /// </summary>
        public void Use<T1, T2, T3, T4>(Action<T1, T2, T3, T4> with) {

            //set a default for each of the params
            T1 param1 = default(T1);
            T2 param2 = default(T2);
            T3 param3 = default(T3);
            T4 param4 = default(T4);

            //get the parameters for this method
            var paramList = with.Method.GetParameters();

            //update each of the parameters            
            string paramName = string.Empty;
            try {
                for (int i = 0; i < paramList.Length; i++) {

                    //find the correct matching property for this parameter
                    paramName = paramList[i].Name;
                    switch (i + 1) {
                        case 1:
                            param1 = this.Get<T1>(paramName);
                            break;

                        case 2:
                            param2 = this.Get<T2>(paramName);
                            break;

                        case 3:
                            param3 = this.Get<T3>(paramName);
                            break;

                        case 4:
                            param4 = this.Get<T4>(paramName);
                            break;
                    }
                }

            }
            catch (Exception ex) {
                throw new ArgumentException(
                    string.Format(EXCEPTION_MISSING_PARAMETER_INFORMATION, paramName),
                    ex
                    );
            }

            //otherwise, execute the method provided
            with(param1, param2, param3, param4);

        }

        #endregion

        #region Working With Arrays

        /// <summary>
        /// Returns the specified property as an array of AnonymousTypes
        /// </summary>
        public AnonymousType[] AsArray(string property) {
            object[] values = this.Get<object[]>(property);
            return values.Select(o => {
                if (o is AnonymousType) { return (AnonymousType)o; }
                return new AnonymousType(o);
            }).ToArray();
        }

        /// <summary>
        /// Performs the specified action on each value in an array of AnonymousTypes
        /// </summary>
        public void WithEach(string property, Action<AnonymousType> action) {
            foreach (AnonymousType value in this.AsArray(property)) {
                action(value);
            }
        }

        #endregion

        #region Static Methods

        /// <summary>
        /// Returns the type of data for the provided object
        /// </summary>
        public static T Get<T>(object data, string property) {
            return new AnonymousType(data).Get<T>(property);
        }

        /// <summary>
        /// Returns the type of data for the provided object
        /// </summary>
        public static T Get<T>(object data, string property, T defaultValue) {
            return new AnonymousType(data).Get<T>(property, defaultValue);
        }

        /// <summary>
        /// Returns the type of data for the provided object
        /// </summary>
        public static AnonymousType[] AsArray(object data, string property) {
            return new AnonymousType(data).AsArray(property);
        }

        /// <summary>
        /// Performs the following action on each of the values in the specified
        /// property value for a user
        /// </summary>
        public static void WithEach(object data, string property, Action<AnonymousType> action) {
            new AnonymousType(data).WithEach(property, action);
        }

        #endregion

    }
}

والنظر بشكل صريح تحويل إلى قائمة وصب ViewData:

ViewData["QUsers"] = (from u in db.Users select u).ToList();

foreach(Users u in (List<Users>)ViewData["QUsers"]){ 

    /*Print the data here*/

}

ويمكنك تمرير البيانات في عدد قليل من الطرق، وذلك باستخدام ViewData كما كنت أعلاه، أو TempData لتمرير بين المجموعات. يمكنك أيضا استخدام ViewData.Model لاحتواء نموذج مكتوب بشدة. لاحظ أنه سيكون لديك لتغيير تعريف بغية يكون شيء من هذا القبيل

ViewPage<User>

وأما بالنسبة للبديل مكرر لطيفة محاولة http://www.codeplex.com/MVCContrib . لديهم شبكة الاكواد مساعد التي يمكن أن تساعد.

إذا كنت ترغب في تجنب خلق طبقة منفصلة فقط للعرض الخاص بك الإسقاط واحد، هل يمكن أن تلجأ أيضا إلى استخدام القاموس، كما يلي:

from person in personList select new Dictionary<string, string>
{ 
    { "Name", person.Firstname + " " + person.Lastname },
    { "Id", person.Id.ToString() }
};

ويمكنك بعد ذلك اكتب viewpage ل

ViewPage<IEnumerable<Dictionary<string, string>>>

وتكرار أخيرا على القائمة في عرض مثل ذلك:

<% foreach (Dictionary<string, string> p in (IEnumerable)ViewData.Model) 
{ %>
   <li> <%=p["Id"] %> - <%= p["Name"] %> </li>
<% } %>

وغني عن القول، والعيب هو أن التعليمات البرمجية هو الآن الكامل بدلا من "سلاسل السحر"، مما يجعلها أكثر عرضة للخطأ بسبب عدم وجود وقت الترجمة فحص.

ولا يمكنك فقط استخدام RouteValueDictionary من MVC؟

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top