فرض كنيد ايميل اطلاع رساني برنامه ASP.Net شما قرار است ايميل زير را پس از تكميل يك فرم ارسال كند.
براي ارسال اين قالب كه مطابق تصوير هر بار بايد سه برچسب آن تغيير كند چه راهي را پيشنهاد ميدهيد؟
راه اول: (راه متداول)
اين فرم را در يك html editor درست كرده و جاي سه برچسب را خالي ميگذاريم. سپس html مورد نظر را در تابع ارسال ايميل خود به صورت يك رشته تعريف نموده و جاهاي خالي را پر خواهيم كرد. مثلا:
string Name = "علي";
string Desc = "منابع مورد نياز";
int Number = 10;
string content =
"<div dir=\"rtl\" style=\"text-align: right; font-family:Tahoma; font-size:9pt\">" +
"با سلام<br />" +
"احتراما آقاي/خانم" +
Name +
" درخواست چاپ" +
Desc +
" داراي" +
Number +
" صفحه را دادهاند. لطفا جهت تائيد درخواست ايشان به برنامه مراجعه بفرمائيد.<br />" +
"<br />" +
"با تشكر</div>";
- الف) امكان مشاهده شكل نهايي تا زمانيكه ايميل مورد نظر را دريافت نكرده باشيم، وجود ندارد.
- ب) اعمال تغييرات جديد به اين فرمت رشتهاي مشكل است. هميشه استفاده از ابزارهاي بصري براي بهبود كار كمك بزرگي هستند كه در اين حالت از آنها محروم خواهيم شد.
- ج)اگر تغيير رسيده جديد، درخواست اضافه كردن ليست پرينتهاي قبلي اين شخص بود چه بايد كرد؟ آيا جدول مورد نظر را بايد به صورت دستي ايجاد و باز هم به صورت يك رشته به اين مجموعه اضافه كرد؟ در اين حالت از كنترلهاي استانداردي مانند GridView و امثال آن محروم خواهيم شد.
- د) هر بار تغيير، نياز به recompile برنامه دارد.
راه دوم: استفاده از قالبها
خوشبختانه در ASP.Net امكان رندر كردن كنترلها به صورت يك string نيز موجود است. در مثال ما نياز است تا چندين كنترل در كنار هم قرار گيرند تا شكل نهايي را ايجاد كنند. بنابراين ميتوان تمام آنها را در يك يوزر كنترل قرار داد. سپس بايد كل يوزر كنترل را به صورت يك رشته، رندر كرد كه در ادامه به آن خواهيم پرداخت.
اگر قالب فوق را بخواهيم در يك يوزر كنترل طراحي كنيم، سورس صفحه html يوزر كنترل به صورت زير خواهد بود (فايل WebUserControl1.ascx) :
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="WebUserControl1.ascx.cs"
Inherits="testWebForms87.WebUserControl1" %>
<div dir="rtl" style="text-align: right; font-family:Tahoma; font-size:9pt">
با سلام<br />
احتراما آقاي/خانم
<asp:Label ID="lblName" runat="server"></asp:Label>
درخواست چاپ
<asp:Label ID="lblDesc" runat="server"></asp:Label>
داراي
<asp:Label ID="lblNumber" runat="server"></asp:Label>
صفحه را دادهاند. لطفا جهت تائيد درخواست ايشان به برنامه مراجعه بفرمائيد.<br />
<br />
با تشكر</div>
public string Name { get; set; }
public int Number { get; set; }
public string Desc { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
lblNumber.Text = Number.ToString();
lblName.Text = Name;
lblDesc.Text = Desc;
}
مرحله بعد، رندر كردن خودكار اين يوزر كنترل و سپس تبديل محتواي حاصل به يك رشته است. براي اين منظور از تابع زير ميتوان كمك گرفت (براي مثال تعريف شده در كلاس دلخواه CLoadUC) :
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Web;
using System.Web.UI;
/// <summary>
/// تبديل يك يوزر كنترل به معادل اچ تي ام ال آن
/// </summary>
/// <param name="path">مسير يوزر كنترل</param>
/// <param name="properties">ليست خواص به همراه مقادير مورد نظر</param>
/// <returns></returns>
/// <exception cref="NotImplementedException"><c>NotImplementedException</c>.</exception>
public static string RenderUserControl(string path,
List<KeyValuePair<string,object>> properties)
{
Page pageHolder = new Page();
UserControl viewControl =
(UserControl)pageHolder.LoadControl(path);
Type viewControlType = viewControl.GetType();
foreach (var pair in properties)
{
PropertyInfo property =
viewControlType.GetProperty(pair.Key);
if (property != null)
{
property.SetValue(viewControl, pair.Value, null);
}
else
{
throw new NotImplementedException(string.Format(
"UserControl: {0} does not have a public {1} property.",
path, pair.Key));
}
}
pageHolder.Controls.Add(viewControl);
StringWriter output = new StringWriter();
HttpContext.Current.Server.Execute(pageHolder, output, false);
return output.ToString();
}
كه البته تابع نهايي آنرا كمي اصلاح كردم تا بتوان ليستي از خواص پابليك يك يوزر كنترل را به آن پاس كرد و محدود به يك خاصيت نبود.
اكنون استفاده از يوزر كنترلي كه تاكنون طراحي كردهايم به سادگي زير است:
List<KeyValuePair<string, object>> lst =
new List<KeyValuePair<string, object>>
{
new KeyValuePair<string, object>("Name", "علي"),
new KeyValuePair<string, object>("Number", 10),
new KeyValuePair<string, object>("Desc", "منابع مورد نياز")
};
string content = CLoadUC.RenderUserControl("WebUserControl1.ascx", lst);