آموزش Angular و ASP.NET Web API (بخش دوم)
بسم الله الرحمن الرحیم
بخش اول آموزش Angular و ASP.NET Web API
بخش دوم آموزش Angular و ASP.NET Web API
بخش سوم آموزش Angular و ASP.NET Web API
بخش دوم ساخت پروژه
در این دوره آموزشی قصد داریم یک پروژه را با استفاده ASP.NET MVC & Web API و همچنین Angular پیاده سازی کنیم.
از این رو آموزش هایی برای این معماری ها قبلا ارائه گردیده است که شما می بایست ابتدا این آموزش ها را مطالعه نمایید تا بتوانیم به سراغ مباحث مربوط به این دوره برویم، پس اگر با این معماری ها آشنایی کاملی ندارید ابتدا از طریق لینک های زیر آموزش های پیش نیاز این دوره را بررسی و مطالعه کنید و سپس به سراغ این آموزش بیاید.
آموزش Angular
آموزش Web API
و در نهایت دوره آموزش Angular و ASP.NET Web API
کدهای این دوره را در پایین همین صفحه قرار داده ام
شروع ساخت پروژه در Visual Studio 2013
از منوی File گزینه New Project را انتخاب کنید. از پنجره باز شده در سمت چپ گزینه Visual C# | Web را انتخاب و سپس از بخش سمت راست .NET Web Application را با .NET Framework 4.5 انتخاب کنید. نام پروژه را GeekQuiz انتخاب و سپس Ok کنید.
بسم الله الرحمن الرحیم
بخش اول آموزش Angular و ASP.NET Web API
بخش دوم آموزش Angular و ASP.NET Web API
بخش سوم آموزش Angular و ASP.NET Web API
بخش دوم ساخت پروژه
در این دوره آموزشی قصد داریم یک پروژه را با استفاده ASP.NET MVC & Web API و همچنین Angular پیاده سازی کنیم.
از این رو آموزش هایی برای این معماری ها قبلا ارائه گردیده است که شما می بایست ابتدا این آموزش ها را مطالعه نمایید تا بتوانیم به سراغ مباحث مربوط به این دوره برویم، پس اگر با این معماری ها آشنایی کاملی ندارید ابتدا از طریق لینک های زیر آموزش های پیش نیاز این دوره را بررسی و مطالعه کنید و سپس به سراغ این آموزش بیاید.
آموزش Angular
آموزش Web API
و در نهایت دوره آموزش Angular و ASP.NET Web API
کدهای این دوره را در پایین همین صفحه قرار داده ام
شروع ساخت پروژه در Visual Studio 2013
از منوی File گزینه New Project را انتخاب کنید. از پنجره باز شده در سمت چپ گزینه Visual C# | Web را انتخاب و سپس از بخش سمت راست .NET Web Application را با .NET Framework 4.5 انتخاب کنید. نام پروژه را GeekQuiz انتخاب و سپس Ok کنید.
در پنجره New ASP.NET Project گزینه MVC را انتخاب و سپس از بخش پایین تیک گزینه Web API را نیز فعال کنید. از بخش سمت چپ Authentication، Individual User Accounts را انتخاب کنید و سپس Ok کنید.
همانطور که می بینید در Visual Studio 2013 شما می توانید قالب (template) اصلی پروژه خود را انتخاب و سپس بخش های مورد نیاز خود را به آن اضافه کنید و تنها در بخش ساخت پروژه Web یک گزینه بیشتر وجود ندارد اما در بخش بعدی آن (یعنی همین پنجره بالا) شما می توانید موارد مورد نیاز خود انتخاب کنید.
در Solution Explorer بر روی پوشه Models کلیک راست کنید و سپس ....Add | Existing Item را انتخاب کنید.
در پنجره Add Existing Item فایل های مشخص شده را که در مسیر Source/Assets/Models قرار دارد Add کنید.
با اضافه کردن این فایل ها، data model و Entity Framework database context و همچنین database initializer شما اضافه خواهد شد.
Entity Framework (EF) یک object-relational mapper (ORM) می باشد که به شما اجازه می دهد تا به داده های خود به وسیله model (به جای دسترسی مستقیم و برنامه نویسی برای relational storage schema) دسترسی داشته باشید.
در این بخش در مورد آموزش EF مطالبی را ارائه داده ایم که می توانید مطالعه کنید.همچنین از پنل سمت چپ (طبقه بندی موضوعی) می توانید در بخش MVC مطالب مفیدی در این خصوص مطالعه کنید.
هر یک از کلاس هایی که اضافه کرده اید را به صورت مختصر توضیح می دهیم.
TriviaOption این کلاس گزینه های پاسخ برای یک سوال را تعریف می کند.
TriviaQuestion این کلاس سوالات را به همراه گزینه های آن مشخص می کند.
TriviaAnswer گزینه ای که توسط کاربر انتخاب شده است را مشخص می کند.
TriviaContext این کلاس مربوط به Entity Framework's database context است. این کلاس از DContext ایجاد شده است و به ازای Entity های ما در آن DbSet تعریف شده است.
TriviaDatabaseInitializer این کلاس پیاده سازی Entity Framework initializer برای TriviaContext می باشد و از کلاس CreateDatabaseIfNotExists ارث می برد. به صورت پیش فرض اگر دیتابیس موجود نباشدف دیتابیس مربوطه را ایجاد خواهد کرد.
فایل Global.asax.cs را باز کنید و کد زیر را در آن قرار دهید.
using GeekQuiz.Models;
کد زیر را در ابتدای متد Application_Start برای تنظیم کردن TriviaDatabaseInitializer به عنوان سازنده دیتابیس قرار دهید.
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
System.Data.Entity.Database.SetInitializer(new TriviaDatabaseInitializer());
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
}
کنترل Home را برای محدود کردن دسترسی کاربران باید به صورت زیر تغییر دهیم. برای اینکار در پوشه Controllers فایل HomeController.cs را باز کنید و سپس خصوصیت Authorize را به کلاس HomeController اضافه کنید.
namespace GeekQuiz.Controllers
{
[Authorize]
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
...
}
}
Authorize filter بررسی می کند تا مشخص شود کاربری که درخواستی برای این Action ارسال کرده است احراز هویت شده است (authenticated) یا خیر. اگر کاربر مورد نظر مجوز دسترسی به این کنترلر را نداشته باشد Authorize filter باعث می شود که بدون اجرا شدن هیچ Action ایی کد وضعیتHTTP 401 به معنای Unauthorized ارسال شود. شما می توانید این فیلتر (Authorize) را به کنترلر به صورت سراسری (مانند این مثال) و یا به هر Action مورد نظر خود نسبت دهید.
برای اطلاعات بیشتر در این خصوص می توانید به مقالات زیر که قبلا در مورد احراز هویت و روش های آن نوشته ایم مراجعه کنید.
برای تغییردادن layout صفحات می بایست فایل _Layout.cshtml را که در پوشه Views | Shared قرار گرفته است باز کنید و سپس به جای مقدار قرار گرفته دورن تگ <title> مقدار Geek Quiz را قرار دهید.
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@ViewBag.Title - Geek Quiz</title>
@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/modernizr")
</head>
در همین فایل، در بخش navigation bar باید تغییراتی را انجام دهیم. لینک های About و Contact را حذف کنید و سپس لینک Home را به Play و درنهایت لینک Application name را به Geek Quiz تغییر دهید. کد شما باید شبیه کد زیر شده باشد
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
@Html.ActionLink("Geek Quiz", "Index", "Home", null, new { @class = "navbar-brand" })
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>@Html.ActionLink("Play", "Index", "Home")</li>
</ul>
@Html.Partial("_LoginPartial")
</div>
</div>
</div>
در بخش footer همین فایل نیز تغییراتی را باید انجام دهیم. عبارت My ASP.NET Application که در تگ P نوشته شده است را به Geek Quiz تغییر دهید.
<div class="container body-content">
@RenderBody()
<hr />
<footer>
<p>© @DateTime.Now.Year - Geek Quiz</p>
</footer>
</div>
در بخش گذشته ساختار پروژه خود را طراحی و ایجاد کردیم. حال باید یک سرویس ساده Web API را به صورت زیر ایجاد کنیم.
GET /api/trivia سوال پاسخ داده شده توسط کاربر را بازیابی می کند.
POST /api/trivia پاسخ ثبت شده توسط کاربر احراز هویت شده را ارسال می کند.
هنگامی که شما از ابزار ASP.NET Scaffolding مربوط به Visual Studio استفاده می کنید، خطوط اصلی برنامه شما نوشته می شود.
در پوشه App_Start فایل WebApiConfig.cs را باز کنید. پیکربندی و تنظیمات مربوط به Web API service مانند route ها که نحوه نگاشت (map) اکشن های کنترلرها را مشخص می کند، در این فایل قرار دارد.
کد زیر را در ابتدای این فایل قرار دهید.
using Newtonsoft.Json.Serialization;
کدهای اضافه شده در بخش زیر را که مشاهده می کنید به متد Register اضافه کنید. این کدها باعث تنظیم فرمت بندی داده های JSON دریافت شده توسط متدهای Web API action می شود.
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Use camel case for JSON data.
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
دستور CamelCasePropertyNamesContractResolver باعث می شود که پراپرتی ها در JavaScript به صورت خودکار به camel تبدیل شوند، این یک قرارداد کلی برای پراپرتی ها در JavaScript می باشد.
در Solution Explorer بر روی پوشه Controllers راست کلیک کنید و سپس گزینه ...Add | New Scaffolded Item را انتخاب کنید.
در پنجره باز شده Add Scaffold، از سمت چپ گزینه Common را انتخاب کنید و سپس از سمت راست Web API 2 Controller – Empty را انتخاب و در نهایت بر روی Add کلیک کنید.
ASP.NET Scaffolding یک code generation framework برای ASP.NET Web application می باشد. (به این می گویند مقاله فارسی!)
Visual Studio 2013 کدهایی را به صورت پیش نویس برای پروژه های MVC و Web API تولید می کند. شما می توانید برای کاهش زمان کد نویسی (برای کدهای تکراری و عملیات های اصلی) از scaffolding در پروژه خود استفاده کنید تا کد نویسی فعالیت های مورد نیاز شما برای model ها انجام شود.
Scaffolding همچنین نیازمندی های یک پروژه را نصب می کند مثلا اگر شما یک پروژه به صورت empty ASP.NET ایجاد کنید و سپس یک کنترلر Web API به آن اضافه کنید، Web API NuGet package های مورد نیاز پروژه به همراه reference ها به صورت خودکار به پروژه شما اضافه می شود.
در پنجره Add Controller نام کنترلر را TriviaController قرار دهید و سپس بر روی Add کلیک کنید.
کنترلر شما اضافه خواهد شد، حال using های زیر را به ابتدای این کلاس اضافه کنید.
using System.Data.Entity;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http.Description;
using GeekQuiz.Models;
کد زیر را به ابتدای کلاس TriviaController برای تعریف، مقدار دهی و dispose کردن (از بین بردن) شی TriviaContext در کنترلر اضافه کنید.
public class TriviaController : ApiController
{
private TriviaContext db = new TriviaContext();
protected override void Dispose(bool disposing)
{
if (disposing)
{
this.db.Dispose();
}
base.Dispose(disposing);
}
}
متد Dispose مربوط به TriviaController، متد Dispose شی TriviaContext را فراخوانی می کند تا تمامی منابع دریافت شده توسط شی context هنگامی که شی TriviaContext از بین می رود و یا garbage-collected اتفاق می افتد، آزاد شود. این عملیات شامل بستن database connection های باز شده توسط Entity Framework نیز می باشد.
متد helper زیر را به انتهای کلاس TriviaController اضافه کنید. این متد پاسخ سوالات ثبت شده توسط یک کاربر خاص را از دیتابیس بازیابی می کند.
private async Task<TriviaQuestion> NextQuestionAsync(string userId)
{
var lastQuestionId = await this.db.TriviaAnswers
.Where(a => a.UserId == userId)
.GroupBy(a => a.QuestionId)
.Select(g => new { QuestionId = g.Key, Count = g.Count() })
.OrderByDescending(q => new { q.Count, QuestionId = q.QuestionId })
.Select(q => q.QuestionId)
.FirstOrDefaultAsync();
var questionsCount = await this.db.TriviaQuestions.CountAsync();
var nextQuestionId = (lastQuestionId % questionsCount) + 1;
return await this.db.TriviaQuestions.FindAsync(CancellationToken.None, nextQuestionId);
}
متد Get زیر را به کلاس TriviaController اضافه کنید. این action method متد helper "NextQuestionAsync " را که در مرحله قبل تعریف کردیم، فراخوانی می کند.
// GET api/Trivia
[ResponseType(typeof(TriviaQuestion))]
public async Task<IHttpActionResult> Get()
{
var userId = User.Identity.Name;
TriviaQuestion nextQuestion = await this.NextQuestionAsync(userId);
if (nextQuestion == null)
{
return this.NotFound();
}
return this.Ok(nextQuestion);
}
متد helper زیر را به کلاس TriviaController اضافه کنید. این متد یک پاسخ مشخص را در دیتابیس ذخیره می کند و یک مقدار Boolean به منظور تعیین اینکه پاسخ صحیح بوده یا خیر بر می گرداند.
private async Task<bool> StoreAsync(TriviaAnswer answer)
{
this.db.TriviaAnswers.Add(answer);
await this.db.SaveChangesAsync();
var selectedOption = await this.db.TriviaOptions.FirstOrDefaultAsync(o => o.Id == answer.OptionId
&& o.QuestionId == answer.QuestionId);
return selectedOption.IsCorrect;
}
متد Post زیر را به کلاس TriviaController اضافه کنید. این متد پاسخ ارسالی را به یک کاربر انتساب و متد StoreAsync helper را فراخوانی می کند، سپس یک مقدار Boolean به وسیله متد helper بر می گرداند.
// POST api/Trivia
[ResponseType(typeof(TriviaAnswer))]
public async Task<IHttpActionResult> Post(TriviaAnswer answer)
{
if (!ModelState.IsValid)
{
return this.BadRequest(this.ModelState);
}
answer.UserId = User.Identity.Name;
var isCorrect = await this.StoreAsync(answer);
return this.Ok<bool>(isCorrect);
}
خصوصیت Authorize را به کلاس TriviaController برای تعیین احراز هویت و محدود کردن دسترسی به این Web API controller اضافه کنید.
[Authorize]
public class TriviaController : ApiController
{
...
}
پروژه خود را اجرا کنید. برای اینکه بتوانیم نتیجه تست را مشاهده کنیم باید از یک مرورگر و ابزار Developer آن مرورگر استفاده کنیم. من شخصا با Mozilla Firefox کار می کنم اما برای اینکه همه بتوانند نتیجه را ببیند از IE در اینجا استفاده می کنیم.
F5 را فشار دهید تا پروژه اجرا شود.
به دلیل تنظیمات مربوط به MVC route به صورت پیش فرض، پس از اجرای وب سایت صفحه Index در HomeController اجرا خواهد شد اما چون کل کنترلر را با خصوصیت Authorize فیلتر کردیم، پس کاربر می بایست برای دسترسی به این صفحه لاگین کند لذا ما به صفحه log in هدایت می شویم.
بر روی لینک Register در منو بالا کلیک کنید، سپس فرم مربوطه را تکمیل و ثبت کنید. حال اگر بالای منو نگاه کنید نامی که ثبت نام کرده اید، مشاهده خواهید کرد، حال مجوز دسترسی به صفحه را خواهید داشت.
در مرورگر IE کلید F12 را بزنید تا ابزار Developer Tools نمایش داده شود. بر روی آیکون Network کلیک کنید و بر روی دکمه سبز رنگ برای ثبت ترافیک مصرف صفحه (capturing network traffic) کلیک کنید.
به ادرس بار مرورگر خود api/trivia را اضافه کنید. متد Get مربوط به TriviaController اجرا خواهد شد.
پس از اجرای کامل دستور صفحه ای برای باز شدن و یا ذخیره محتوا نمایش داده می شود، با این dialog box کاری نخواهیم داشت. برای مشاده اطلاعات کامل از اجرای این دستور، بر روی لینک Details و سپس بر روی Response body کلیک کنید (مشابه تصویر).
شما می توانید داده ایی که دانلود شده است را مشاهده کنید، در این داده یک شی با پراپرتی های options (یک لیست از شی های TriviaOption می باشد)، id و title بر اساس کلاس TriviaQuestion وجود دارد.
دریافت کدهای پروژه WebAPI and Angular
حمید
database پروژه کجاست ؟؟
مهدی
سلام.ضمن تشکر صمیمانه میخوا ستم بدونم فایلهای
TriviaAnswer.cs , TriviaContex.cs
و غیره رو از کجا باید پیدا کنم؟
من یه همچین فایلهایی تو کامپیوترم ندارم.
ممنون میشم اگه راهنمایی کنین چو اگه نتونم فایلها رو به پروژه اضافه کنم نیمه کاره یاد گرفتم همه چیز رو.با تشکر
چون ایمیلم رو هم گذاشتم اگه کسی این فایلها رو داره برام بفرسته.ممنون میشم.
علی میلادیان
اسماعیلشیدایی
با عرض سلام
بنده از لطف شما بسیار متشکرم
هدف ما افزایش سطح علمی جامعه نرم افزار است، شما هم به نوبه ی خود می توانید با انتشار مطالبتان، و یا معرفی این وب سایت به سایر دوستان درخواست کمک از آنها برای رشد افراد دیگر به ما کمک کنید.
موفق باشید
یاعلی