سؤال

في الماضي ، استخدمت USERCONTROLS لإنشاء قوالب بريد إلكتروني يمكنني ملء الخصائص عليها ثم استخدام LOADCONTROL ثم تقديم CONCONTROL للحصول على HTML التي يجب استخدامها لنص جسم بريدي الإلكتروني. كان هذا داخل ASP.NET WebForms.

أنا في رميات بناء موقع ويب MVC وأردت القيام بشيء مماثل. لقد فكرت بالفعل في وضع هذه الوظيفة في مكتبة فصل منفصلة وأبحث في كيفية القيام بذلك ، بحيث يمكنني فقط في طبقة الويب الخاصة بي الاتصال بـ eMailTemplate.SubscriptionEmail () والتي ستنشئ HTML من القالب الخاص بي مع الخصائص ذات الصلة الأماكن (من الواضح أنه يجب أن تكون هناك معلمات لعنوان البريد الإلكتروني وما إلى ذلك).

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

public static string RenderUserControl(string path,
                 string propertyName, object propertyValue)
        {
            Page pageHolder = new Page();
            UserControl viewControl =
               (UserControl)pageHolder.LoadControl(path);

            if (propertyValue != null)
            {
                Type viewControlType = viewControl.GetType();
                PropertyInfo property = viewControlType.GetProperty(propertyName);
                if (property != null)
                    property.SetValue(viewControl, propertyValue, null);
                else
                {
                    throw new Exception(string.Format(
                       "UserControl: {0} does not have a public {1} property.",
                       path, propertyName));
                }
            }

            pageHolder.Controls.Add(viewControl);
            StringWriter output = new StringWriter();
            HttpContext.Current.Server.Execute(pageHolder, output, false);
            return output.ToString();
        }

مشكلتي هي أن usercontrol (ق) قد يكون لها خصائص متعددة واختلاف. لذا ، قد يتطلب المشتركين FirstName و EmailAddress حيث يتطلب قالب بريد إلكتروني آخر USERCONTROL (يتيح الاتصال به DummemyMail) FirstName و EmailAddress و DateOfbirth.

تظهر الطريقة أعلاه فقط لحمل معلمة واحدة لـ PropertyName و PropertyValue. لقد فكرت في مجموعة من الأوتار التي يمكنني وضعها في الخصائص المختلفة ، لكن بعد ذلك اعتقدت أنه سيكون من الرائع أن يكون لديك كائن intialiser حتى أتمكن من تسمية الطريقة مثل هذه:

RenderUserControl("EmailTemplates/SubscribeEmail.ascs", new object() { Firstname="Lloyd", Email="myemail@mydomain.com" })

هل هذا منطقي؟ كنت أتساءل فقط عما إذا كان هذا ممكنًا على الإطلاق في المقام الأول وكيف سأطبقه؟ لست متأكدًا مما إذا كان من الممكن تعيين الخصائص المحددة على "كائن" لخصائص عنصر تحكم المستخدم المحمّل وإذا كان من الممكن أن تبدأ في القيام بذلك؟

هل فعل أي شخص شيئًا كهذا من قبل؟ هل أستطيع مساعدتك؟

لويد

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

المحلول

يمكن تنفيذ مثالك. لكنه ينتهك نمط MVC قليلا جدا. وإذا كنت تفعل ذلك على أي حال ، فقد تذهب أيضًا مع نفس الحل الذي كان لديك في WebForms.

عندما أقوم بإنشاء بريد HTML ، عادةً ما أقوم بإنشاء عرض MVC عادي (مع إجراء على بعض وحدة التحكم وعرض العرض). ثم أقوم بإعداد هذا العرض إلى سلسلة وأرسله بعيدًا. وبهذه الطريقة ، تتابع نمط MVC وستحصل على القدرة على رؤية البريد في المتصفح تلقائيًا (يمكنك فقط زيارة عنوان URL لهذا الإجراء. يمكن بالطبع تقييد هذا بأي طريقة تريدها).

لتقديم طريقة عرض لسلسلة أستخدمها هذه الفئة:

public class ViewRenderer
{
    protected RouteCollection RouteCollection { get; private set; }

    public DefaultViewRenderer()
        : this(RouteTable.Routes)
    {

    }

    public DefaultViewRenderer(RouteCollection routeCollection)
    {
        RouteCollection = routeCollection;
    }

    public virtual string RenderViewAsString<TController>(Expression<Action<TController>> action)
        where TController : Controller
    {
        var sb = new StringBuilder();
        var memWriter = new StringWriter(sb);

        var fakeContext = CreateFakeContext(memWriter);

        var oldContext = HttpContext.Current;
        HttpContext.Current = fakeContext;

        CreateHtmlHelper(fakeContext).RenderAction(action);

        HttpContext.Current = oldContext;

        memWriter.Flush();
        memWriter.Dispose();
        return sb.ToString();
    }

    protected virtual HttpContext CreateFakeContext(StringWriter memWriter)
    {
        var fakeResponse = new HttpResponse(memWriter);
        var context = new HttpContext(HttpContext.Current.Request, fakeResponse);

        foreach (var key in HttpContext.Current.Items.Keys)
            context.Items[key] = HttpContext.Current.Items[key];

        foreach (string key in HttpContext.Current.Session.Keys)
            context.Session[key] = HttpContext.Current.Session[key];

        return context;
    }

    protected virtual HtmlHelper CreateHtmlHelper(HttpContext fakeContext)
    {
        var fakeControllerContext = CreateControllerContext(fakeContext, RouteCollection);
        return new HtmlHelper(new ViewContext(fakeControllerContext,
                                                  new FakeView(), new ViewDataDictionary(), new TempDataDictionary()), new FakePage());
    }

    protected virtual ControllerContext CreateControllerContext(HttpContext fakeContext, RouteCollection routeCollection)
    {
        return new ControllerContext(
            new HttpContextWrapper(fakeContext),
            routeCollection.GetRouteData(new HttpContextWrapper(HttpContext.Current)), new FakeController());
    }

    protected class FakeView : IView
    {
        public void Render(ViewContext viewContext, TextWriter writer)
        {
            throw new NotImplementedException();
        }
    }

    protected class FakeController : Controller
    {

    }

    protected class FakePage : IViewDataContainer
    {
        public ViewDataDictionary ViewData
        {
            get { return new ViewDataDictionary(); }
            set { }
        }
    }
}

هذا يستخدم استجابة مزيفة تكتب نتيجة العرض في stringBuilder. ثم تستخدم هذا مثل هذا:

var viewRenderer = new ViewRenderer();
var body = viewRenderer.RenderViewAsString<SomeController>(x => x.ActionThatRendersHtmlMail(parameters));

ثم يمكنك فقط إرسال البريد مع نص الجسم هذا. يمكنك بالطبع لف هذا الفصل الخاص بك حتى تتمكن من الاتصال بـ eMailTemplate.subscriptionEmail () ؛ (من مثالك).

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