sv2.Add(t2);
t1.ListTb2.Add(t2);
sv2.Add(t2);
t1.ListTb2.Add(t2);
http://services.odata.org/OData/OData.svc/Category(1)/Products?$top=2&$orderby=name \_______________________________________/ \__________________/ \__________________/ | | | service root URL resource path query options
http://services.odata.org/OData/OData.svc/Products
http://services.odata.org/OData/OData.svc/Products(1)/Supplier
http://services.odata.org/OData/OData.svc/Products/MostExpensive
http://services.odata.org/OData/OData.svc/GetProductsByCategoryId(categoryId=2)
http://services.odata.org/OData/OData.svc/Products(1)/Name
//filter http://services.odata.org/OData/OData.svc/Products?$filter=Name eq 'Milk' //orderby http://services.odata.org/OData/OData.svc/Products?$orderby=Name //skip http://services.odata.org/OData/OData.svc/Products?$skip=5 //top http://services.odata.org/OData/OData.svc/Products?$top=10 //expand http://services.odata.org/OData/OData.svc/Products?$expand=Category
using System;
namespace System.Web.Mvc
{
public abstract class WebViewPage<TModel> : WebViewPage
{
protected WebViewPage();
public AjaxHelper<TModel> Ajax { get; set; }
public HtmlHelper<TModel> Html { get; set; }
public TModel Model { get; }
public ViewDataDictionary<TModel> ViewData { get; set; }
public override void InitHelpers();
protected override void SetViewData(ViewDataDictionary viewData);
}
}
<head>
<title>@ViewBag.Title</title>
<link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
</head>
namespace MvcApplication18.Models
{
public class Employee
{
public int Id { set; get; }
public string Name { set; get; }
}
}
using System.Collections.Generic;
namespace MvcApplication18.Models
{
public static class EmployeeDataSource
{
public static IList<Employee> CreateEmployees()
{
var list = new List<Employee>();
for (int i = 0; i < 1000; i++)
{
list.Add(new Employee { Id = i + 1, Name = "name " + i });
}
return list;
}
}
}
using System.Linq;
using System.Web.Mvc;
using MvcApplication18.Models;
namespace MvcApplication18.Controllers
{
public class HomeController : Controller
{
[HttpGet]
public ActionResult Index()
{
return View();
}
[HttpPost] //for IE-8
public ActionResult EmployeeInfo(int? id)
{
if (!Request.IsAjaxRequest())
return View("Error");
if (!id.HasValue)
return View("Error");
var list = EmployeeDataSource.CreateEmployees();
var data = list.Where(x => x.Id == id.Value).FirstOrDefault();
if (data == null)
return View("Error");
return PartialView(viewName: "_EmployeeInfo", model: data);
}
}
}
@model MvcApplication18.Models.Employee
<strong>Name:</strong> @Model.Name
@{
ViewBag.Title = "Index";
}
<h2>
Index</h2>
<div id="EmployeeInfo">
@Ajax.ActionLink(
linkText: "Get Employee-1 info",
actionName: "EmployeeInfo",
controllerName: "Home",
routeValues: new { id = 1 },
ajaxOptions: new AjaxOptions
{
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "EmployeeInfo",
LoadingElementId = "Progress"
})
</div>
<div id="Progress" style="display: none">
<img src="@Url.Content("~/Content/images/loading.gif")" alt="loading..." />
</div>
[AttributeUsage(AttributeTargets.Class|AttributeTargets.Method)]
public class AjaxOnlyAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.HttpContext.Request.IsAjaxRequest())
{
base.OnActionExecuting(filterContext);
}
else
{
throw new InvalidOperationException("This operation can only be accessed via Ajax requests");
}
}
}
[AjaxOnly]
public ActionResult SomeAjaxAction()
{
return Content("Hello!");
}
<a data-ajax="true" data-ajax-loading="#Progress" data-ajax-method="POST"
data-ajax-mode="replace" data-ajax-update="#EmployeeInfo"
href="/Home/EmployeeInfo/1">Get Employee-1 info</a>
<a href="#" onclick="LoadEmployeeInfo()">Get Employee-1 info</a>
@section javascript
{
<script type="text/javascript">
function LoadEmployeeInfo() {
showProgress();
$.ajax({
type: "POST",
url: "/Home/EmployeeInfo",
data: JSON.stringify({ id: 1 }),
contentType: "application/json; charset=utf-8",
dataType: "json",
// controller is returning a simple text, not json
complete: function (xhr, status) {
var data = xhr.responseText;
if (status === 'error' || !data) {
//handleError
}
else {
$('#EmployeeInfo').html(data);
}
hideProgress();
}
});
}
function showProgress() {
$('#Progress').css("display", "block");
}
function hideProgress() {
$('#Progress').css("display", "none");
}
</script>
}
@RenderSection("javascript", required: false)
[HttpPost] //for IE-8
public ActionResult EmployeeInfoData(int? id)
{
if (!Request.IsAjaxRequest())
return Json(false);
if (!id.HasValue)
return Json(false);
var list = EmployeeDataSource.CreateEmployees();
var data = list.Where(x => x.Id == id.Value).FirstOrDefault();
if (data == null)
return Json(false);
return Json(data);
}
<a href="#" onclick="LoadEmployeeInfoData()">Get Employee-2 info</a>
@section javascript
{
<script type="text/javascript">
function LoadEmployeeInfoData() {
showProgress();
$.ajax({
type: "POST",
url: "/Home/EmployeeInfoData",
data: JSON.stringify({ id: 1 }),
contentType: "application/json; charset=utf-8",
dataType: "json",
// controller is returning the json data
success: function (result) {
if (result) {
alert(result.Id + ' - ' + result.Name);
}
hideProgress();
},
error: function (result) {
alert(result.status + ' ' + result.statusText);
hideProgress();
}
});
}
function showProgress() {
$('#Progress').css("display", "block");
}
function hideProgress() {
$('#Progress').css("display", "none");
}
</script>
}
[HttpPost] //for IE-8
public ActionResult SearchEmployeeInfo(string data)
{
if (!Request.IsAjaxRequest())
return Content(string.Empty);
if (string.IsNullOrWhiteSpace(data))
return Content(string.Empty);
var employeesList = EmployeeDataSource.CreateEmployees();
var list = employeesList.Where(x => x.Name.Contains(data)).ToList();
if (list == null || !list.Any())
return Content(string.Empty);
return PartialView(viewName: "_SearchEmployeeInfo", model: list);
}
@model IEnumerable<MvcApplication18.Models.Employee>
<table>
<tr>
<th>
Name
</th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
</tr>
}
</table>
@using (Ajax.BeginForm(actionName: "SearchEmployeeInfo",
controllerName: "Home",
ajaxOptions: new AjaxOptions
{
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "EmployeeInfo",
LoadingElementId = "Progress"
}))
{
@Html.TextBox("data")
<input type="submit" value="Search" />
}
<form action="/Home/SearchEmployeeInfo" data-ajax="true"
data-ajax-loading="#Progress" data-ajax-method="POST"
data-ajax-mode="replace" data-ajax-update="#EmployeeInfo"
id="form0" method="post">
<input id="data" name="data" type="text" value="" />
<input type="submit" value="Search" />
</form>
$.validator.unobtrusive.parse("#{form-id}");
$.ajax
({
url: "/{controller}/{action}/{id}",
type: "get",
success: function(data)
{
$.validator.unobtrusive.parse("#{form-id}");
}
});
//or
$.get('/{controller}/{action}/{id}', function (data) { $.validator.unobtrusive.parse("#{form-id}"); });
@using (Ajax.BeginForm(
"Action1",
"Controller",
null,
new AjaxOptions {
OnSuccess = "onSuccess",
UpdateTargetId = "result"
},
null)
)
{
<input type="submit" value="Save" />
}
var onSuccess = function(result) {
// enable unobtrusive validation for the contents
// that was injected into the <div id="result"></div> node
$.validator.unobtrusive.parse("#result");
};
using System.Web.Mvc;
namespace MvcApplication1.Controllers
{
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
return View();
}
}
}
using System.Web.Mvc;
namespace MvcApplication2.Controllers
{
public class HomeController : Controller
{
[NonAction]
public string ShowData()
{
return "Text";
}
public ActionResult Index()
{
ViewBag.Message = string.Format("{0}/{1}/{2}",
RouteData.Values["controller"],
RouteData.Values["action"],
RouteData.Values["id"]);
return View();
}
public ActionResult Search(string data = "*")
{
// do something ...
return View();
}
}
}
using System.Web.Mvc;
namespace MvcApplication2.Controllers
{
public class ActionResultsController : Controller
{
//http://localhost/actionresults/welcome
public string Welcome()
{
return "Hello, World";
}
//http://localhost/actionresults/index
public ActionResult Index() // or ContentResult
{
return Content("Hello, World");
}
//http://localhost/actionresults/SendMail
public void SendMail()
{
}
public ActionResult SendMailCompleted() // or EmptyResult
{
// do whatever
return new EmptyResult();
}
public ActionResult GetFile() // or FilePathResult
{
return File(Server.MapPath("~/content/site.css"), "text/css", "mySite.css");
}
public ActionResult UnauthorizedStatus() // or HttpStatusCodeResult/HttpUnauthorizedResult
{
return new HttpUnauthorizedResult("You need to login first.");
}
public ActionResult Status() // or HttpStatusCodeResult
{
return new HttpStatusCodeResult(501, "Server Error");
}
public ActionResult GetJavaScript() // or JavaScriptResult
{
return JavaScript("...JavaScript...");
}
public ActionResult GetJson() // or JsonResult
{
var obj = new { prop1 = 1, prop2 = "data" };
return Json(obj, JsonRequestBehavior.AllowGet);
}
public ActionResult RedirectTo() // or RedirectResult
{
return RedirectPermanent("http://www.site.com");
//return RedirectToAction("Home", "Index");
}
public ActionResult ShowView() // or ViewResult
{
return View();
}
}
}
[TestMethod]
public void TestMethod1()
{
// Arrange
var controller = new ActionResultsController();
// Act
var result = controller.Index() as ContentResult;
// Assert
Assert.NotNull(result);
Assert.AreEqual( "Hello, World", result.Content);
}
مخلص کلام اینکه : اگه با Fody یا PostSharp و همچنین Code Analyzerها آشنایی دارین. این قابلیت یه چیزی تو مایههای ترکیب ایناس و بهتون اجازه میده موقع Compile شدن کد پروژه رو Analyze کنین و یه کد جدیدی بهش اضافه کنین. (مثلا پیاده سازی اینترفیس INotifyPropertyChanged به صورت خودکار به هنگام کامپایل)
We’re pleased to introduce the first preview of Source Generators, a new C# compiler feature that lets C# developers inspect user code and generate new C# source files that can be added to a compilation. This is done via a new kind of component that we’re calling a Source Generator.
To get started with Source Generators, you’ll need to install the latest .NET 5 preview and the latest Visual Studio preview.
نمونه ای از پیاده سازی INotifyPropertyChanged with C# 9.0 Source Generators
enable-migrations add-migration Initial -IgnoreChanges update-database
using System.Data.Entity.Migrations; using System.Data.Entity.Migrations.Design; namespace EFTests { /// <summary> /// Using Entity Framework Code First with an existing database. /// </summary> public static class CreateMigrationHistory { /// <summary> /// Creates a new '__MigrationHistory' table. /// Enables migrations using Entity Framework Code First on an existing database. /// </summary> public static void UpdateDatabase(DbMigrationsConfiguration configuration) { var scaffolder = new MigrationScaffolder(configuration); // Creates an empty migration, so that the future migrations will start from the current state of your database. var scaffoldedMigration = scaffolder.Scaffold("IgnoreChanges", ignoreChanges: true); // enable-migrations // add-migration Initial -IgnoreChanges configuration.MigrationsAssembly = new MigrationCompiler(ProgrammingLanguage.CSharp.ToString()) .Compile(configuration.MigrationsNamespace, scaffoldedMigration); // update-database var dbMigrator = new DbMigrator(configuration); dbMigrator.Update(); } } }
using System; using System.CodeDom.Compiler; using System.Collections.Generic; using System.ComponentModel; using System.Data.Common; using System.Data.Entity; using System.Data.Entity.Migrations; using System.Data.Entity.Migrations.Design; using System.Data.Entity.Spatial; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Resources; using System.Text; namespace EF_General.Models.Ex22 { public enum ProgrammingLanguage { CSharp, VB } public class MigrationCompiler { private readonly CodeDomProvider _codeProvider; public MigrationCompiler(string language) { _codeProvider = CodeDomProvider.CreateProvider(language); } public Assembly Compile(string @namespace, params ScaffoldedMigration[] scaffoldedMigrations) { var options = new CompilerParameters { GenerateExecutable = false, GenerateInMemory = true }; options.ReferencedAssemblies.Add(typeof(string).Assembly.Location); options.ReferencedAssemblies.Add(typeof(Expression).Assembly.Location); options.ReferencedAssemblies.Add(typeof(DbMigrator).Assembly.Location); options.ReferencedAssemblies.Add(typeof(DbContext).Assembly.Location); options.ReferencedAssemblies.Add(typeof(DbConnection).Assembly.Location); options.ReferencedAssemblies.Add(typeof(Component).Assembly.Location); options.ReferencedAssemblies.Add(typeof(MigrationCompiler).Assembly.Location); options.ReferencedAssemblies.Add(typeof(DbGeography).Assembly.Location); var embededResources = GenerateEmbeddedResources(scaffoldedMigrations, @namespace); foreach (var resource in embededResources) options.EmbeddedResources.Add(resource); var sources = scaffoldedMigrations.SelectMany(g => new[] { g.UserCode, g.DesignerCode }); var compilerResults = _codeProvider.CompileAssemblyFromSource(options, sources.ToArray()); foreach (var resource in embededResources) File.Delete(resource); if (compilerResults.Errors.Count > 0) { throw new InvalidOperationException(BuildCompileErrorMessage(compilerResults.Errors)); } return compilerResults.CompiledAssembly; } private static string BuildCompileErrorMessage(CompilerErrorCollection errors) { var stringBuilder = new StringBuilder(); foreach (CompilerError error in errors) { stringBuilder.AppendLine(error.ToString()); } return stringBuilder.ToString(); } private static IEnumerable<string> GenerateEmbeddedResources(IEnumerable<ScaffoldedMigration> scaffoldedMigrations, string @namespace) { foreach (var scaffoldedMigration in scaffoldedMigrations) { var className = GetClassName(scaffoldedMigration.MigrationId); var embededResource = Path.Combine( Path.GetTempPath(), @namespace + "." + className + ".resources"); using (var writer = new ResourceWriter(embededResource)) { foreach (var resource in scaffoldedMigration.Resources) writer.AddResource(resource.Key, resource.Value); } yield return embededResource; } } private static string GetClassName(string migrationId) { return migrationId .Split(new[] { '_' }, 2) .Last() .Replace(" ", string.Empty); } } }
CreateMigrationHistory.UpdateDatabase(new Configuration());
public class Configuration : DbMigrationsConfiguration<MyContext> { public Configuration() { AutomaticMigrationsEnabled = true; AutomaticMigrationDataLossAllowed = true; } }