ورود

View Full Version : آموزش: آشنایی با Ajax در ASP.MVC - سیستم ثبت نظردهی



hakim22
پنج شنبه 07 شهریور 1392, 01:38 صبح
دانلود فایل پروژه به همراه متن کامل مقاله به صورت PDF (http://s3.picofile.com/file/7912974622/ASP_MVC_AJAX_1.rar.html)

AJAX چیست ؟
این کلمه مخفف عبارت asynchronous JavaScript and XML می باشد. این یعنی از جاوا اسکریپت و XML به صورت نامگام استفاده کنیم. منظور از ناهمگام بودن این است که درخواست شما به سرور ارسال میشود و بلافاصله به کاربر(Client) برگشت میکند. در این لحظه کاربر میتواند کار خود را در صفحه ی وب ادامه دهد. به محض اینکه پیامی از سمت سرور در پاسخ به درخواست دریافت شود مرورگر آن را به صفحه ی وب اطلاع میدهد.
کاربردها
درحالت معمول بعد از هر درخواست (Request) صفحه ی مرورگر تازه (Refresh) میوشد. برای صفحات کم حجم ممکن است زیاد به نظر نرسد. اما در صفحه های شلوغ این کار برای چند لحظه ارتباط کاربر با صفحه ی وب را مختل میکند. AJAX باعث میشود بروز رسانی صفحه در پس زمینه صورت گیرد و کار کاربر نرم ادامه پیدا کند.
در خیلی از موارد نیاز داریم تنها بخشهایی از صفحه ی وب را بروز کنیم. اگر قرار باشد با هر بار تغییر نتیجه ی بازی فوتبال یا هر بار دریافت پیام همه ی صفحه را بروز کنیم علاوه بر اینکه صفحه در سمت کلایت برای مدتی از دسترس خارج میشود فشار زیادی به سرور وارد میکند. چرا که همه ی اطلاعات باید از نو خوانده شده و به سمت کاربر ارسال شود.
در نهایت AJAX هم سرعت کار با صفحه ی وب را افزایش میدهد و هم بار ترافیکی آن را کم میکند. همچنین طراحی UI را بسیار کاربر پسند تر میکند.
اطلاعات کلی
اول باید بدانید که AJAX برنامه نویسی در سمت Client است و یک قابلیت در جاوا اسکریپت شمرده میشود. اگر شما جاوااسکریپت بلد باشید با هر زبان برنامه نویسی وب میتوانید از AJAX استفاده کنید. برای برنامه نویسی ناهمگام در سمت سرور در ASP از کلاسهای دات نت استفاده میشود.
اگرچه استفاده از jQuery کار کردن با AJAX را بسیار ساده میکند. اما در محیط برنامه نویسی ASP.MVC 4 بهتر است از کمک AJAX یا همان AjaxHelper استفاده کنید. دلیل اول این است که کد نویسی آن ساده تر است و دلیل دوم این است که فریم ورک jquery.unobtrusive-ajax.js خودش همه ی کدهای جاوا اسکریپت مورد نیاز را در صفحه درج میکند و نیاز به نوشتن کدهای جاوا اسکریپت را به حداقل میرساند.
AJAX میتواند در پاسخ به رویداد Submit یک فرم یا کلیک روی یک عکس یا حرکت موس فعال شود. در این مورد محدویتی وجود ندارد.

برنامه ی نمونه
در برنامه ی نمونه تلاش میکنیم یک سیستم نظر دهی به مطلب برای یک سایت ساده طراحی کنیم. دقت کنید که برای ساده سازی سایت تنها شامل یک مطلب است و اطلاعات نظر ها بعد از ارسال به سرور در یک لیست ذخیره میشود. در صورتی که صفحه را refresh کنید پاک خواهد شد. هدف از این پروژه نمایش سیکل رفت و برگشت داده و اثبات این قضیه که صفحه به طور کامل بروز نمیشود بوده است. در ادامه تصویر سایت را مشاهده می کنید :
109850
میبینید مطلبی داریم که که قبلا دو کاربر درباره ی آن نظر ثبت کرده اند. در قسمت درج نظر یک فرم وجود دارد که شما میتوانید با وارد کردن اطلاعات و زدن دکمه ی ثبت نظر جدید ثبت کنید. سرور به محض دریافت اطلاعات فرم، آن را در بانک ذخیره میکند و نتیجه را دوباره به کاربر (کلاینت) برگشت میدهد. این اطلاعات برگشتی میتواند هر چیزی باشد( مثلا پیامی که اعلام کند اطلاعات در سرور ثبت شده است). در اینجا ما عین نظر ثبت شده را به انتهای لیست نظرات قبلی اضافه می کنیم.
جادو چگونه اتفاق می افتد !؟
برای پیاده سازی این فرم در ساده ترین حالت ابتدا به یک کنترلر نیاز دارید . این کنترلر با نام Home دارای یک اکشن با نام Index است و صفحه ای که مطلب در آن قرار دارد را نمایش میدهد. این اکشن نظراتی که قبلا در مورد مطلب در بانک ثبت شده است را در می آورد و سپس آنها را در قابل یک مدل به View اصلی با نام Index منتقل می کند. تا اینجای کار هیچ ربطی به AJAX ندارد و شما فقط دارید عصای جادوگری را دستانتان تاب میدهید.
حالا به View رفته و کدهای آن قسمت را پیاده می کنیم. میتوانید آن را با استفاده از گزینه ی Scafold template روی حالت Edit خیلی سریع باز سازی کنید.
109849
اگر هم دستی View را پیاده می کنید یادتان باشد که مدلی که برای ثبت اطلاعات فرم به آن نیاز دارید در بالای صفحه مشخص کنید
@model MyBlog.Web.Models.Comment

سپس عنوان صفحه ، عنوان مطلب و محتویات مطلب نمایش داده میشود.

<h2>خوش آمدید</h2>
<p style="font-weight: bold; color: maroon">
آشنایی با Ajax در ASP.MVC

</p>
<p style="border: 1px solid black; width: 400px; word-wrap: break-word; margin: 10px; padding: 10px;">
AJAX چیست ؟
این کلمه مخفف عبارت asynchronous JavaScript and XML می باشد. این یعنی از جاوا اسکریپت و XML به صورت نامگام استفاده کنیم. منظور از ناهمگام بودن این است که درخواست شما به سرور ارسال میشود و بلافاصله به کاربر(Client) برگشت میکند. در این لحظه کاربر میتواند کار خود را در صفحه ی وب ادامه دهد. به محض اینکه پیامی از سمت سرور در پاسخ به درخواست دریافت شود مرورگر آن را به صفحه ی وب اطلاع میدهد.

</p>



سپس قسمت نظرات قرار میگیرد. برای خواندن اطلاعات نظرها چندین روش وجود دارد. ساده ترین روش این است که نظرات را در کنترلر Home و در اکشن Index که همین صفحه را نمایش میدهد بخوانید و درون یک ViewBag ذخیره کنید. بعد این اطلاعات را در صفحه نمایش دهید.


@{
IEnumerable<MyBlog.Web.Models.Comment> comments;
comments = ViewBag.comments;
}
<p>نظرات </p>
<div id="comments" style="border: 1px solid maroon; width: 400px; margin: 10px; padding: 10px;">
@foreach (var item in comments)
{
@Html.Partial("_Comment", item);
}
</div>



دقت کنید که خود نظرات در قالب یک PartialView قرار میگیرند و سپس نمایش داده میشوند. محتویان این View به صورت زیر است :

@model MyBlog.Web.Models.Comment

<div id="comment" style="border-bottom :1px solid steelblue;width:400px; padding:10px 0">

@Html.DisplayNameFor(model => model.Name)
<text>:</text>
@Html.DisplayFor(model => model.Name)
<div class="display-label">
@Html.DisplayNameFor(model => model.Email)
<text>:</text>
@Html.DisplayFor(model => model.Email)
</div>
<div class="display-label">
@Html.DisplayNameFor(model => model.Text)
<text>:</text>
@Html.DisplayFor(model => model.Text)
</div>
</div>



این View با درون یک فایل مجزا با نام _comment.cs در فولدر Home ذخیره میشود. از کاراکتر زیر خط (_) برای مشخص کردین اینکه ویو به صورت PartialView است استفاده شده و الزامی ندارد.
برنامه وقتی در حلقه به خط @Html.Partial("_Comment", item) میرسد ایم آن را با اطلاعات item پر میکند و نتیجه در ویو درج میشود.
تا اینجای کار هم از AJAX هیچ استفاده ای نشده است. نمایش لیست نظرات سایت هنگامی صورت میگیرد که صفحه برای اولین بار درحال بارگذاری است.
در اینجا میتوانید نظر را با استفاده از یک فرم ساده و کمک Html.BeginForm بسازید. فرم بعد از Submit شدن به سرور میرود و نتیجه نیز به سمت کاربر برگشت داده میشود. اما این عمل باعث تازه شدن کل صفحه میشود که منجر به بازخوانی دوباره ی همه ی نظرات و سپس اجرای دوبارهی همه ی مراحل قبل میشود.(در این برنامه ی نمونه چون اطلاعات درون کلاس کنترل ذخیره میشود و نه در بانک یا فایل بعد از Refresh شدن پاک میشود و شما نظر ارسالی را نمی بینید.)

@using (Html.BeginForm("submitComment"))

بجای اینکار میتوانید از Ajax.BeginForm استفاده کنید . در این صورت مطلب به سرور ارسال میشود و سرور تنها اطلاعات آخرین نظر ارسالی به Client باز میگرداند و تنها همین اطلاعات در انتهای لیست نظرات درج میشود.
در ساده ترین طراحی نمونه ی کد Ajax در ASP.MVC4 به صورت زیر است :

@using (Ajax.BeginForm("submitComment",
"Home",
new AjaxOptions
{
HttpMethod = "POST",
InsertionMode = InsertionMode.InsertAfter,
UpdateTargetId = "comments"
}
))


اولین آرگومان ورودی به این دستور نام اکشنی است که میخواهید اطلاعات به آن ارسال شود. که در اینجا اکشنی با نام SubmitComment است. آرگومان دوم نام کنترلری است که اکشن در آن قرار دارد. اگر اکشن SubmitComment درون همان کنترلری قرار داشته باشد که این صفحه از آن اجرا شده باشد نوشتن آن نیاز نیست. در اینجا اکشن Index که صفحه را نمایش میدهد با SubmitComment هر دو در کنترلر Home قرار دارند.
مهمترین قسمت در دستور Ajax مربوط به AjaxOptions میشود. در اینجا متد Http برای ارسال داده ها انتخاب میشود. میتوانید از GET هم استفاده کنید.
قسمت InsertionMode به مرورگر میگوید که با اطلاعاتی که بعدا از سرور بازگشت داده میشود چه کند. اگر آن را روی InsertAfter تنظیم کرده باشید اطلاعات بازگشتی بعد از تگ

<div id="comments">
...
</div>



درج میشوند. آدرس تگی که میخواهید آپدیت کنید در گزینه ی UpdateTargetId مشخص میکنید.

بهتر است در اینجا مطمئن شوید که در _Layout مربوط به پروژه یا در همین صفحه اسکریپت مربوط به Ajax را بارگذاری کرده اید .

<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>


معمولا وقتی از Scafold Template استفاده میکنید خودش آدرس دهی به اسکریپت را از طریق اضافه کردن کد زیر به انتهاب View انجام میدهد.

@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
} 

سایر اطلاعات فرم به صورت زیر است :

{
@Html.AntiForgeryToken()
@Html.ValidationSummary(true)
<fieldset style="width: 400px;">
<legend>درج نظر</legend>
<div class="editor-label">
@Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
@Html.EditorFor(model => model.Name)
@Html.ValidationMessageFor(model => model.Name)
</div>
سایر input ها برای دریافت اطلاعات مدل و ارسال آن به سرور...
<p>
<input type="submit" value="ثبت" />
</p>
</fieldset>
}



بعد از آنکه دکمه ی ثبت زده میشود اطلاعات در قالب یک درخواست post اما در حالت Ajax به سرور ارسال میشود. اکشنی که درخواست را دریافت میکند با نام SubmitComment مشخص شده است.
public ActionResult SubmitComment(Models.Comment model)
{
// TODO : save model to a database
return PartialView("_Comment", model);
}
در اینجا نظرثبت شده توسط کاربر در سمت Client به سرور میرسد. سرور نوع آن را تشخیص میدهد و مقدارش را درون متغیر model میریزد. سپس شما میتوانید اطلاعات دریافتی را در بانک اطلاعاتی ذخیره کنید. یا هرکاری که دلتان میخواهد ! با آن بکنید.
در گام بعد ما همان مدل دریافتی را مستقیما به PartialView که قبلا با نام _Comment ساخته بودیم منتقل می کنیم. موتور razor محتوای HTML را میسازد و آن را به AJAX در سمت کاربر ارسال می کند. در سمت کاربر وقتی محتوای نظر به صورت HTML دریافت شد آن را بعد از تگ با آیدی Comment درج می کند.
109851

بلافاصله بعد از اینکه نظر به سرور انتقال داده شد شما میتوانید یک نظر جدید دیگر از طریق فرم ثبت کنید. چیزی شبیه ارسال نظرات در سایتهایی مانند Facebook یا خیلی سایتهای دیگر.
در قسمت Network از Developer Tools در مرورگر IE که با کلید F12 فعال میشود میتوانید رویداد های شبکه را بررسی کنید. در اینجا بعد از زده شدن دکمه ی ثبت و submit شدن فرم یک Request از نوع POST به سرور انتقال داده میشود. در اینجا پروژه ما به پایان میرسد. و یک سیکل کامل از کار با AJAX را پیاده سازی کردیم.
مدل نظر به صورت زیر است.
public class Comment
{ public int Id { get; set; }
[DisplayName("نام")]
public string Name { get; set; }
[DisplayName("ایمیل")]
public string Email { get; set; }
[DisplayName("نظر")]
public string Text { get; set; }
} 
نکته ی آخر اینکه چنانچه کاربر جاوا اسکریپتش را غیر فعال کند فرم کار خواهد کرد ولی اطلاعات برگشتی بجای همه ی اطلاعات قبلی در صفحه قرار میگیرد و به طور کامل Replace میشود. برای مدل کردن این کار میتوانید از Developer tools در IE و منوی Disable استفاده کنید.
در سمت سرور میتوانید این حالت را با استفاده از متد Request.IsAjaxRequest() تشخیص دهید. چون ممکن از یک اکشن هم برای حالت Ajax هم برای حالت همگام استفاده شود با استفاده از یک شرط این قضیه در سمت سرور بررسی میشود.
public ActionResult SubmitComment(Models.Comment model)
{
// TODO : save model to a database

if (Request.IsAjaxRequest())
{
return PartialView("_Comment", model);
}
else
{
//--- TODO: If not ajax call
}

}
پایان مقاله

دانلود فایل پروژه به همراه متن کامل مقاله به صورت PDF (http://s3.picofile.com/file/7912974622/ASP_MVC_AJAX_1.rar.html)

alireza_rashvand
شنبه 08 شهریور 1393, 17:07 عصر
با سلام
سپاس از اموزش خیلی خوبتون, گرچه این تاپیک برای یک سال قبله ولی واقعا بنده در همین جای طراحی سایتم گیر کردم بد جور بالا پایین می کنم بازهم نمی شه , اگر بتونید کمکم کنید واقعا ممنون می شم. در یک تاپیک دیگه مشکلم رو توضیح دادم ولی اینقدر بد توضیح دادم ترجیه میدم به انجا لینک ندم.
مشکلم رو خیلی کوتاه بیان می کنم. اگر دوستان یا شما اقای عبدالحکیم قدس می توانید کمکم کنید خواهشا دریغ نفرمایید...
پروژه سایت خبری را مدنظر قرار دادم رسیدم به قسمت نمایش خبر, یعنی فرد در صفحه اول وقتی روی تیر کلیک کرد می ره به صفحه نمایش خبر,
صفحه شامل : خبر + ثبت نظر+نمایش نظرات,
یعنی فرد خبر رو بالا می بینه بعد ابزار ثبت نظر و پایین اون نظرات دیگران رو مشاهده می کنه(دقیقا مثل همین مقاله شما)...
در ابتدا یک اکشن لینک قرار داده بودم و در یک ویو دیگه نظرات رو ثبت می کردم بر می گشتم به نمایش خبر, ولی می خواهم رفت و برگشتی نداشته باشم نظر را در ذیل پست ثبت کنم بعد از ثبت هم صفحه رفرش بشه (یا به صورتی که شما نوشتید فقط نظرات رفرش بشه)
پس صفحه ما نیاز به یک پارشال برای نمایش, یک فرم برای ثبت نظر و یک پارشال برای نمایش نظرات دارد...
بنابرین نیاز به دوتا جدول داریم 1- پست 2- نظرات...
شما اینجا از یک مدل استفاده کردید ولی حتمالا نیاز به ویومدل داریم(اگر اشتباه می کنم بگید)
ویو مدلی که طراحی کردم به این صورت است:


public class PostCommentsViewModel
{
public Post PostInfo { get; set; }
public List<Comment> ShowCMs { get; set; }

//این خط زیر رو مطمئن نیستم درست نوشته باشم, برای ثبت نظر اضافه کردم
public Comment InsertCm { get; set; }

public PostCommentsViewModel(int? Id)
{
var db = new Context();
PostInfo = db.Posts.First(x => x.Id == Id);
var query = from x in db.Comments where x.PostId == Id select x;
ShowCMs = query.ToList();
}
}

یه جا دیدم به این صورت از سازنده خود کلاس استفاده کرده , به نظر خوب بود, ولی اگر به نظرتون اشکالی در این ویومدل هست بفرمایید.
در ابتدا اطلاعات پست(PostInfo) و بعد لیستی از نظرات(ShowCMs) تعریف کردم که در سازنده هر دو مقدار دهی می شود

ولی وقتی می خواستم فرم ثبت نظر را ایجاد کنم نیاز بود مدل(model => ) برنامه را مشخص کنم(کد زیر)

@Html.TextBoxFor(model => model.InsertCm.Name)

برای همین هم InsertCm را تعریف کردم (البته در سازنده مقدار دهی نمی شود آیا باید شود یا نشود نمی دانم)
در نمایش خبر و نمایش لیست نظرات هیچ مشکلی ندارم ولی وقتی دکمه ثبت نظر رو میزنم در ثبت نظر دچار مشکل میشم, (کد ثبت نظر):

public ActionResult InsertComment(Comment comment, int id))
{
Post post = db.Posts.Find(id);
if (this.ModelState.IsValid)
{
using (db)
{
db.Comments.Add(new Comment
{
Name = comment.Name,
Content = comment.Content,
PostId = id,
DateCreated = DateTime.Now
});
db.SaveChanges();

ViewBag.info = "با موفقیت ثبت شد";
}
}
return PartialView("_ShowComment", comment);
}


مشکل اینجاست که با اینکه در سمت ویو مقادیر را وارد می کنم ولی در اکشن مقدار مدل خالی است یعنی comment که از مودل Comment است مقادیر را بعد از زدن دکمه ثبت نظر بر نمی گرداند(null) ...
حتی مدل اکشن InsertComment را از Comment به ویو مدل PostCommentsViewModel تغییر می دهم بازهم نمی شود.

به نظرتون تا این جای کار چه اشتباهی انجام داده ام؟
چرا مقادیر به اکشن بر نمی گردد؟
مدل اکشن ثبت نظر چگونه باید باشد؟
مدل اجزائی فرم ثبت نظر باید چگونه باشد؟

اگر برای حل مشکل اطلاعات بیشتر لازم است بفرمایید تا توضیح دهم.

hakim22
شنبه 08 شهریور 1393, 21:34 عصر
اول اینکه استفاده از Constructor در ViewModel اونو پیچیده میکنه و به نظر من اصلا مناسب نیست. به خصوص به این شیوه که شما استفاده کرده اید.

به نظر من کلاسهای Model و ViewModel باید خالص و خالی هر کد اجرایی باشند. برای Initialization شما میتوانید از الگوی Service استفاده کنید. در واقع تعریف ابتدایی شی گرایی را در MVC کمی باید کنار بگذارید. حداقل در مورد Model و ViewModel استفاده از این روش مناسب نیست.

شما یک ViewModel برای نمایش پست باید داشته باشید و یک ViewModel کاملا مجزا برای Comment :


public class CommentInsertModel
{
public int PostId { get; set; }


[DisplayName("نظر ")]

public string Description { get; set; }


public int UserInsertId { get; set; }

}


اگر نیاز به Id پست دارید آن را درون ViewModel قرار دهید. شما می توانید در یک View از چندین ViewModel استفاده کنید و همچنین چند فرم همزمان داشته باشید. قسمت نمایش پست با قسمت نظرات دو کد و ViewModel جدا از هم دارند.(یعنی نیازی نیست درون هم تعریف شوند)


public class PostViewModel
{
public int Id { get; set; }
public string Title { get; set; }
public string Body { get; set; }
public int UserInsert { get; set; }
public string TimeInsert { get; set; }

}

alireza_rashvand
یک شنبه 09 شهریور 1393, 02:42 صبح
شما می توانید در یک View از چندین ViewModel استفاده کنید و همچنین چند فرم همزمان داشته باشید.

سپاس از کمکی که کردید.
مگه ما به خاطر محدودیتی که در استفاده از یک model در یک view داریم از ViewModel استفاده نمی کنیم؟
منظورتان از چندین ViewModel در یک view رو لطفا توضیح بدید.
مثلا اگر یک ViewModel برای نمایش خبر همراه با نظراتش داشته باشم, و یک ViewModel دیگه برای ثبت نظر , چگونه می توانم ان را در یک ویو استفاده کنم.؟
مثلا:

// برای استفاده از اطلاعات پست و نظرات ViewModel مورد نظر رو مشخص می کنم
@model Projects.ViewModels.PostCommentsViewModel


//برای نمایش پست
@Html.Partial("_ShowPosts", @Model.PostInfo)


//برای نمایش نظرات
@foreach (var item in Model.ShowComments)
{
@Html.Partial("_ShowComment", item)
}




حالا اگر بخواهم ثبت نظر هم داشته باشم و از یک model یا ViewModel دیگه استفاده کنم چطوری باید ان را در View مشخص کنم؟

مسلما چنین کاری اشتباه است :(مشخص کردن دو مدل هم زمان )

@model Projects.ViewModels.PostCommentsViewModel
@model Projects.ViewModels.InsertCommentViewModel


پس چگونه؟

hakim22
یک شنبه 09 شهریور 1393, 08:23 صبح
استفاده از ViewModel دلایل زیادی دارد.

1- چون Model ها مستقیما نماینده یک جدول در بانک اطلاعاتی هستند و بانکهای اطلاعاتی تغییر می کنند استفاده از ViewModel کمک می کند وابستگی بین جداول دیتابیس و ویو ها از بین برود.
2- هیچ مدلی به تنهایی کامل نیست. چون در بانکهای اطلاعاتی اطلاعات با استفاده از کلیدهای خارجی (Id) بهم وصل میشوند و هنگام نمایش اطلاعات باید این کلیدهای خارجی را بازیابی کنید.
3- با کمک ViewModel و نامگذاری دقیق آنها می توانید هدف از هر View را مشخص کنید و آن را در یک چهارچوب کاری مشخص قراردهید.

استفاده از ابزاری مثل AutoMapper کمک می کند انتقال اطلاعات بین Model و ViewModel راحت تر صورت گیرد.

این روش البته نیاز به کد نویسی بیشتر دارد و زحمت شما را در طراحی اولیه کم نمیکند. اما مدیریت تغییرات پروژه را در آینده راحت تر می کند.

شما می توانید با استفاده از کمک Helper.Action@ یک ActionResult یا PartialView را در هر جای ویو فراخوانی کنید. این دستور اکشن مربوطه را اجرا می کند و خروجی آن را که معمولا PartialView است در همان محل فراخوانی درج میکند.

ویوی پست شما یک ViewModel اصلی مثلا PostViewModel خواهد داشت. در حقیقت همه ی View مربوط به پست شما به شکل زیر خواهد شد :


@{
ViewBag.Title = Model.Title;
}


<div class="panel panel-default">
<div class="panel-body">
@Html.Partial("_Post")
</div>

</div>


@Html.Partial("_InsertComment", new CommentInsertModel() { PostId = Model.Id })


@Html.Action("_LatestComments", "Comments", new { postId = Model.Id })


@Html.Action("_LastPosts", "Post", new { area = "Blog" })






سمت کنترلر :


public PartialViewResult _Review(int id)

public ActionResult _InsertComment(CommentInsertModel comment)

public PartialViewResult _LatestComments(int postId)

public PartialViewResult _LastPosts()



علاوه بر اینکه این روش خواناتر هست و تغییر قسمتهای مختلف کد آن راحتتر و سریعتر و مجزا از سایر بخشها صورت می گیرد شما در اینجا می توانید از تکنیک Donut Caching هم استفاده کنید. یعنی قسمت Review که اصل پست را نمایش میدهد با استفاده از OutputCache کش کنید ولی سایر قسمتها که تغییر می کنند کش نکنید.

alireza_rashvand
سه شنبه 11 شهریور 1393, 03:19 صبح
بازهم سپاس, نکات بسیاری را در توضیحات یاد گرفتم ولی برای اینکه وقتتان را نگیرم به موضوع های اصلی که هنوز برام حل نشده است می پردازم, (مطالبتان را کاملا و چند بار خوانم)


حرفتان کاملا درست است نباید مستقیم با مودل دیتابس در ارتباط بود. و بهتر است برای استفاده از مودل دیتابیس از ویومدل استفاده کنیم که اطلاعات مورد نیاز ما را به ما می دهد(هرچیزی که نیاز داریم نه همه), این جوری امکان دسترسی به اطلاعات مهم را از سواستفاده کنندگان هم می گیرم,
ولی به نظرم رسید شما اعتقادی به این موضوع ندارید که در یک ViewModel از چند Model استفاده بشه,
اعتقادتان براین است که به ازای هر Model از دیتابیس یک ViewModel داشته باشیم,



ویوی پست شما یک ViewModel اصلی مثلا PostViewModel خواهد داشت.

شما یک ویومدل اصلی در نظر گرفتید مثلا PostViewModel که اطلاعات مورد نیاز نمایش پست را در خود دارد
و در صورت نیاز به ViewModel های دیگراین گونه عمل می کنید

@Html.Partial("_InsertComment", new CommentInsertModel() { PostId = Model.Id })


یعنی شما مودل مورد نیاز اکشن _InsertComment که از نوع ویومدل CommentInsertModel است را به این صورت در اختیارش قرار میدید, درسته؟

new CommentInsertModel() { PostId = Model.Id }

البته از کد بالا ایراد می گیرد با خطا همراه است , خودتان امتحان کنید.



واقعیت اینکه تا به حال ندیده بودم از این روش استفاده بشه!

من فکر می کردم اگر نیاز به چند مودل داشته باشیم ان ها را در یک ویو مدل جمع می کنیم و با معرفی ان به view امکان استفاده از چند مودل (http://www.dotnettips.info/post/1243/%D9%86%D8%AD%D9%88%D9%87-%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D8%A7%D8%B2-viewmodel-%D8%AF%D8%B1-asp-net-mvc) برای ما فراهم می شود

ولی به نظرم می رسه شما در طراحی ویومدل از چند مودل استفاده نکردید بلکه برای هر مدل یک ویومدل ساختید.



(یعنی نیازی نیست درون هم تعریف شوند)



واقعا شرمنده اگر زیاد سوال میکنم وقتتان را می گیرم.

hakim22
سه شنبه 11 شهریور 1393, 09:37 صبح
البته من کدها رو از یک پروژه کامل و بدون خطا کپی کردم. اگر خطا را ذکر میکردید شاید برای آن راه حلی باشد.

من در ساختن ViewModel صزفه جویی نمیکنم و هیچوقت تا به حال نیاز نشده از چند مدل درون یک ViewModel استفاده کنم.

روش بالا کمک می کند کد شما همیشه قابل استفاده ی مجدد باشد. مثلا من اگر بخواهم آخرین پستها را در صفحه ی اول نمایش دهم ، با فراخوانی یک خط کد در ویوی مربوطه کارم تمام میشود.

ضمن اینکه این روش به ویو ها ساختار دقیقی می دهد و شما می توانید به راحتی آن را عیب یابی یا تغییر دهید. مثلا من اگر بعدا احساس کردم نیازی به نمایش تیتر آخرین پستها در زیر نظرات ندارم آن یک خط را بر میدارم و کار تمام است. در حالی که اگر ViewModel تو در تو تعریف کرده بودم باید ویو مدل را هم عوض می کردم.

بخواهید یا نخواهید هیچ کدی کامل نیست و خیلی زود نیاز به تغییر و بروز رسانی در آن احساس میشود.

پس کدها باید برای تغییر آمادگی داشته باشند. هر تغییری که در یک سیستم ایجاد می کنید یک ضربه به آن سیستم است. کنترل عواقب آن گاهی می تواند بسیار مشکل باشد.بهتر است کمترین وابستگی بین کدها وجود داشته باشد تا بتوانید با آرامش بیشتری تغییرات و بهینه سازی را در آینده انجام دهید.

black-cn
جمعه 08 آبان 1394, 09:53 صبح
با سلام و ممنون بابت پست خوبتون با اینکه آخرین ارسال مال بیش از یک سال پیشه ولی ممنون میشم تو مشکلم منو راهنمایی کنین


مشکل من اینجاس که
شما یک سایت مثل فیسبوک رو در نظر بگیرین که بیش از یک پست رو در هر صفحه نمایش میده حالا وقتی من برای هر کدوم از پست ها کامنت ارسال میکنم، نظرات مربوط به اولین پست آپدیت میشه ؟

hakim22
جمعه 08 آبان 1394, 15:53 عصر
هر پستی یک PostId داره . در ثبت نظر به همراه اطلاعات Comment یک فیلد PostId به سرور ارسال میشه. فرقی نمیکنه شما چند پست در یک صفحه نمایش میدید تا وقتی دارای PostId هستند هنگام ثبت نظر روی همان پست ثبت میشود.

black-cn
جمعه 08 آبان 1394, 16:43 عصر
بله دقیقا
ولی اتفاقی که میوفته خلاف گفته شما و سواد کم بندس . به هر حال این مشکل فقط بعد از ارسال کامنت بوجود میاد و با رفرش کردن صفحه همه چی درسته (یعنی ثبت اطلاعات مشکلی نداره وهمینطور آی دی مربوط به پست )من چند بار کدهارو چک کردم ولی بازهم مشکل پابرجا هست . حتی PostId بازگشتی به پارشیال ویو مربوط به نمایش کانتها هم درسته


@{ Html.RenderAction("InsertComment", "Comments", new { id = @item.postid });}

و اکشن مربوط

public ActionResult InsertComment(int id) {
ViewBag.id = id;
var cmd = db.Comments.Where(a => a.PostId == id);
ViewBag.comments = cmd;
return PartialView("_InsertCommentPartial"); }

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult InsertComment(Comment comment, int id) {
if (ModelState.IsValid) {
comment.Date = DateTime.Now;
comment.ApplicationUserId = User.Identity.GetUserId();
comment.PostId = id;
db.Comments.Add(comment);
db.SaveChanges();
return PartialView("_ViewCommentsPartial",comment);
} else { return View(); } }

و نهایتا partial view


@model Social.Models.Comment
<li> <div class="media"> <a href="" class="pull-right"> <span>@Model.Commenttext</span> <div class="comment-date">@Model.Date</div> </div> </div> </li>