结合实体框架(代码优先)、工作单元测试、Web API、ASP. net等,以存储库设计模式开发示例项目。NET MVC 5和引导
介绍 这篇文章将帮助你理解在库模式、实体框架、Web API、SQL Server 2012、ASP中的工作单元测试的帮助下设计一个项目。净MVC应用程序。我们正在开发一个图书实体和作者专用的样例图书保存解决方案项目,在该项目上我们可以进行创建、读取、更新和删除操作。 这个计划将包括一旦我们完成了五个相互依赖的次要项目。 总结本项目的成果 这将帮助你开发/设计一个项目在一个多层治理如何定义一个主键的属性的类代码第一种方法如何定义一个属性与decimal数据类型和插入值it 在代码中第一种方法如何定义类的一个国外关键属性在代码中第一种方法如何为一个类的属性定义一个唯一键代码中第一种方法如何安装项目实体框架项目级别OOP方法的例子Overloading 使用为web api方法创建模型自定义URI填充自定义下拉列表和绑定。如何返回一个十进制值作为web方法的响应。如何配置重载可以发送多个参数的web方法。如何从MVC. 调用WebAPI控制器端点如何在创建/编辑视图中绑定下拉菜单在非强类型方式和强类型方式 体系结构 完成项目后,此映像包含解决方案资源管理器中的项目列表。 ,,,,,,,,,,,,,,,,,,,,,,,,,, , 1. LibraryApp。核心-实体和接口 类库——在这个项目中我们包括了类库。 实体界面 基本上,我们可能有两个实体,即书和作者。我们可以使用这个项目的领域实体和数据库操作的接口。根据项目要求,我们可以将即将到来的实体或接口保留在这里。 2只LibraryApp。基础设施——业务逻辑和数据库配置 类库-在这个项目中,我们正在定义 数据库Configuarations 我们可以引用我们的connectionstring 用于数据库连接和其他数据库配置 ,数据库操作 存储库——我们在这里定义了我们在核心项目中处理的Infromations/Entities/ object的数据库操作。对于每个实体,我们可以创建单独的类文件作为存储库,或者我们可以在单个存储库类中包含所有操作。 ,库 我们将使用什么库来执行数据库操作。比如实体框架库或Dapper (Micro ORM)或任何其他技术。 3.LibraryApp。单元测试-工作测试单元 单元测试-在这个项目中,我们正在观察 基础设施项目存储库的单元测试。我们可以验证所有我们写的代码,,,,,,基础设施项目运行正常,如果它们如我们预期的那样运行,我们可以保证基础设施的正常运行。,,项目将在Web服务项目中正常运行。 4. LibraryApp。WebAPI - Web服务 Web API 在这个项目中,我们正在出版 通过在此项目中实例化和引用我们以前的基础设施项目,并且通过一些配置,我们可以将基础设施项目中包含的所有操作发布为web服务。在这里,我们将它们作为HTTP方法发布。我们将这些HTTP方法标识为APIController方法。 ,,,,,, 我们使用这个项目作为服务器和客户端之间的桥梁 服务器端 ,,, LibraryApp.Core ,,, LibraryApp.Infrastructure 桥 ,,,LibraryApp.WebAPI 客户端 ,,,, LibraryApp.MVC 一旦我们发布了这些数据库操作,我们就可以使用它们来创建前端,作为web (ASP)。NET MVC或WebForm应用程序,移动应用程序或桌面应用程序。 5. LibraryApp。MVC -前端端 ASP。NET MVC 5 -在我们执行的这个项目中 如上所述,在这个项目中,我们将创建前端客户端应用程序作为web应用程序。在这里我们use ASP。NET MVC 5和引导程序为我们的任务。 此外,下面的图片解释了上面每个单独的项目是如何相互作用的 , ,,,,,, 操作 主仪表板作者列表创建一本书,编辑一本书,删除一本书,创建一名作家,编辑一名作家,删除一名作家 本公共关系的运作oject 描绘here 主仪表板-书籍列表与作者 作者仪表板-作者列表 创建一个书 编辑一本书 创建一个作者 编辑一个作者 , 数据库 我们使用Enitiy框架代码优先的方法开发这个项目,项目完成后,数据库结构将如下所示。 规范 在这些用主键约束和INT数据类型定义的表id中,您将知道如何用“代码优先”方法为类的属性定义主键 所有的名称和标题定义为NVARCHAR字段,那么任何语言和字母数字字符都可以插入到这里。这里我用僧伽罗语存储了一些数据。 实现 从这里开始,我将逐步解释如何在代码级实现上面的项目。 步骤for LibraryApp.Core 1. 创建空c#类库项目,命名为“ProjectName.Core” 2. 通过右键单击该项目解决方案,插入两个(2)新的文件夹作为“实体”和“接口” 3.现在为我们想要包含的实体/对象在实体文件夹中创建类文件 Book.cs 我们将书表的价格作为十进制值保存在这里,然后您将知道如何用代码优先的方法定义具有十进制数据类型的属性 书表author_id&o将作为存储authoriegn Id的外键。按照本文了解更多关于如何用代码优先的方法为类的属性定义外键的知识 隐藏,复制Code
public class Book
{
public Book()
{ } [Key]
public int Book_Id { get; set; } // Primary Key Constraint [Required]
public string Book_Title { get; set; } [DataType("decimal(16 ,3")]
public decimal Price { get; set; } public string Edition { get; set; } [ForeignKey("Author")]
public int Author_Id { get; set; } // Foriegn Key Constraint public Author Author { get; set; }
}
Author.cs 作者表的Last_Name列是用唯一键约束来构建的。按照这篇文章来进一步了解如何用代码优先的方法为类的属性定义唯一键 隐藏,复制Code
public class Author
{
public Author()
{ } [Key]
public int Auth_Id { get; set; } // Primary Key Constraint [StringLength(50)]
public string First_Name { get; set; }
[Index("IX_FirstAndSecond", 1, IsUnique = true)]
[StringLength(50)]
public string Last_Name { get; set; } // Unique Key Constraint public string Biography { get; set; } [StringLength(1)]
[Column(TypeName = "char")]
public string IsEmployed { get; set; } public ICollection<Book> Books { get; set; }
}
正如您在操作图像中看到的,我们可能有少量下拉列表,因此,为了将值绑定到这些下拉列表,我们在这里使用另一个实体作为基础 Basic.cs 隐藏,复制Code
public class Basic
{
public int ID { get; set; }
public string NAME { get; set; }
}
在我们的仪表盘视图中,除了主实体之外,还有一些不同的属性,因此,这里我们使用了另一个实体BookWithAuthor BookWithAuthor.cs 隐藏,复制Code
public class BookWithAuthor
{
public int BookWithAuthor_Id { get; set; } public string BookWithAuthor_Title { get; set; }
public string BookWithAuthor_AuthorName { get; set; } public decimal Price { get; set; } public string Edition { get; set; }
}
现在我们在核心项目的接口文件夹中创建接口 IBookRepository.cs 隐藏,复制Code
public interface IBookRepository
{
void AddBook(Book book); void EditBook(Book book); void RemoveBook(int Book_Id); IEnumerable<Book> GetBooks(); Book FindBookById(int Book_Id);
}
IAuthorRepository.cs 隐藏,复制Code
public interface IAuthorRepository
{
void AddAuthor(Author author); void EditAuthor(Author author); void RemoveAuthor(int Id); IEnumerable<Author> GetAuthors(); Author FindAuthorById(int Id);
}
IBasic.cs 隐藏,复制Code
public interface IBasic
{
IEnumerable<Basic> GetAuthorsIdName(); // Authors Drop Down IEnumerable<Basic> GetEditionIdName(); // Book Edition Drop Down IEnumerable<Basic> GetEmplyeeStatusIdName(); // Employee Status Drop Down
}
IBooksWithAuthorsRepository.cs 隐藏,复制Code
public interface IBooksWithAuthorsRepository
{
IEnumerable<BookWithAuthor> GetBooksWithAuthors(); // Main Dashboard Authors With Books BookWithAuthor FindBooksWithAuthorsById(int BookWithAuthor_Id); // Get Book Details
}
在这个地下室结束后,解决方案将如下 ,,,,,,,,,,,,,,,,,,,,, 步骤for LibraryApp.Infrastructure 1. 创建空c#类库项目,命名为“ProjectName.Infrastructure” 2. 通过右击该项目解决方案或使用包管理器控制台,安装实体框架。按照本文了解更多关于如何安装实体框架的知识 3只给System.Data。引用中的实体引用 4. 给,LibraryApp。参考文献中的核心参考 5. Define connectionstring App.Config App.Config 安装Entity Framework后,我们可以看到在这个项目中创建的App.Config文件。后& lt; / configSections>标记我们插入这个连接字符串,记住:我们在其余的三个(3)个项目中使用相同的连接字符串 隐藏,复制Code
<connectionStrings>
<addname="libraryappconnectionstring"connectionString="Data Source=.\sqlexpress;Initial Catalog=LibraryAppDB;Integrated Security=True;MultipleActiveResultSets=true"providerName="System.Data.SqlClient"/>
</connectionStrings>
6. 现在创建上下文类文件来定义数据库配置 LibraryContext.cs 我们在web中引用连接字符串。配置,以及需要在数据库中生成的表 隐藏,复制Code
public class LibraryContext : DbContext
{
public LibraryContext() : base("name=libraryappconnectionstring") // Connection String
{ }
// Tables goin to create in Database
public DbSet<Book> Books { get; set; } public DbSet<Author> Authors { get; set; } }
7. 在接口中声明的存储库类中实现方法。 正如我前面提到的,您可以为每个实体创建单独的存储库,或者像这样在单个存储库中添加每个操作。 LibraryRepository.cs 这是整个项目中最重要的类,因为我们操作业务逻辑。简单地说就是要显示什么细节以及要执行什么/如何操作。 在这个存储库类中,我们继承了Core project中包含的所有接口,然后我们可以实现在接口中声明的那些方法。 这里我使用实体框架的Linq to SQL方法来执行我们的操作。 隐藏,收缩,复制Code
public class LibraryRepository : IBookRepository,
IAuthorRepository,
IBooksWithAuthorsRepository,
IBasic
{ LibraryContext context = new LibraryContext(); #region //-----------Books with Authors // Books List with Authors First Name + Last Name
public IEnumerable<BookWithAuthor> GetBooksWithAuthors()
{
var bookswithauthors = (
from book in context.Books
join author in context.Authors
on book.Author_Id equals author.Auth_Id
select new BookWithAuthor
{
BookWithAuthor_Id = book.Book_Id,
BookWithAuthor_Title = book.Book_Title,
BookWithAuthor_AuthorName = author.First_Name + " " + author.Last_Name,
Edition = book.Edition,
Price = book.Price
}).ToList(); return bookswithauthors;
} // Find book details along with author name using book id
public BookWithAuthor FindBooksWithAuthorsById(int BookWithAuthor_Id)
{
var bookwithauthor = (
from book in context.Books
join author in context.Authors
on book.Author_Id equals author.Auth_Id
where book.Book_Id == BookWithAuthor_Id
select new BookWithAuthor
{
BookWithAuthor_Id = book.Book_Id,
BookWithAuthor_Title = book.Book_Title,
BookWithAuthor_AuthorName = author.First_Name + " " + author.Last_Name,
Edition = book.Edition,
Price = book.Price
}).FirstOrDefault(); return bookwithauthor;
} #endregion
#region //-----------Books // Add a Book
public void AddBook(Book book)
{
context.Books.Add(book);
context.SaveChanges();
} // Edit a Book
public void EditBook(Book book)
{
context.Entry(book).State = System.Data.Entity.EntityState.Modified;
context.SaveChanges();
} //Find book by id
public Book FindBookById(int Book_Id)
{
var c = (from r in context.Books where r.Book_Id == Book_Id select r).FirstOrDefault();
return c;
} // Get books
public IEnumerable<Book> GetBooks()
{
return context.Books;
} // Delete a book
public void RemoveBook(int Book_Id)
{
Book book = context.Books.Find(Book_Id);
context.Books.Remove(book);
context.SaveChanges();
} //Get book price by book Id
//OOP - Method Overloading
public decimal findBookPrice(int? book_id)
{
var bookprice = (
from r in context.Books
where r.Book_Id == book_id
select r.Price
).FirstOrDefault(); return bookprice;
} //Get book price by book Id and book name
//OOP - Method Overloading
public decimal findBookPrice(int? book_id, string bookname)
{
var bookprice = (
from book in context.Books
where book.Book_Id == book_id | book.Book_Title == bookname
select book.Price
).FirstOrDefault(); return bookprice;
} #endregion #region //-----------Authors // Add an author
public void AddAuthor(Author author)
{
context.Authors.Add(author);
context.SaveChanges();
} // Edit an author
public void EditAuthor(Author author)
{
context.Entry(author).State = System.Data.Entity.EntityState.Modified;
context.SaveChanges();
} // Find an author by id
public Author FindAuthorById(int Author_Id)
{
var c = (from r in context.Authors where r.Auth_Id == Author_Id select r).FirstOrDefault();
return c;
} // Get author list
public IEnumerable<Author> GetAuthors()
{
return context.Authors;
} // Delete an author
public void RemoveAuthor(int Author_Id)
{
Author author = context.Authors.Find(Author_Id);
context.Authors.Remove(author);
context.SaveChanges();
} #endregion #region //-----------DropDowns // Populate author id and name dropdown
public IEnumerable<Basic> GetAuthorsIdName()
{
var authoridname = (
from author in context.Authors
select new Basic
{
ID = author.Auth_Id,
NAME = author.First_Name + " " + author.Last_Name
}).ToList(); return authoridname;
} // Populate book edition id,name dropdown and binding using Model
public IEnumerable<Basic> GetEditionIdName()
{
return new List<Basic>(new[]
{
new Basic()
{
ID = 1,
NAME = "1st Edition"
},
new Basic()
{
ID = 2,
NAME = "2nd Edition"
}
// Add more Editions
});
} // Populate book employee status,id dropdown and binding using Model
public IEnumerable<Basic> GetEmplyeeStatusIdName()
{
return new List<Basic>(new[]
{
new Basic()
{
ID = 1,
NAME = "Y"
},
new Basic()
{
ID = 2,
NAME = "N"
}
});
} #endregion }
8. 通过插入代码优先方法中的样本数据来初始化数据库 LibraryDbInitalize.cs 隐藏,收缩,复制Code
public class LibraryDbInitalize : DropCreateDatabaseIfModelChanges<LibraryContext>
{
protected override void Seed(LibraryContext context)
{
//Adding initial Author data
context.Authors.Add
(
new Author
{
Auth_Id = 1,
First_Name = "Author FirstName 001",
Last_Name = "Author LastName 001",
Biography = "Author 1st Bio",
IsEmployed = "Y"
}
); //Adding initial Book data
context.Books.Add
(
new Book
{
Book_Id = 1,
Book_Title = "Book Title 001",
Edition = "1st Edition",
Price = 40.0M, //this is how insert values to decimal field in code level
Author_Id = 1
}
); context.SaveChanges(); base.Seed(context); }
}
本LibraryApp结束。基础设施项目,结构如下所示 ,,,,,,,,,,,,,,,,,,,,,,, 现在我们将测试在repository类中实现的方法 步骤for LibraryApp.UnitTest 1. 创建空c# Unit Test 项目,命名为“ProjectName.UnitTest” 2. 在app.config文件中添加connectionstring,就像上面的项目一样 3.在引用中给出libraryapp . core和libraryapp . infrastructurereferences 通过右键单击该项目解决方案,插入一个类并将其命名为“ProjectNameRepositoryTest” LibraryRepositoryTest.cs 隐藏,收缩,复制Code
public class LibraryRepositoryTest
{
LibraryRepository Repo; // initialize the test class
[TestInitialize]
public void TestSetup()
{
LibraryDbInitalize db = new LibraryDbInitalize();
System.Data.Entity.Database.SetInitializer(db);
Repo = new LibraryRepository();
} #region Author // check valid number of author/s(1) existing in current DB
[TestMethod]
public void IsRepositoryInitalizeWithValidNumberOfData_Author()
{
var result = Repo.GetAuthors();
Assert.IsNotNull(result);
var numberOfRecords = result.ToList().Count;
Assert.AreEqual(1, numberOfRecords);
} // check add author method working and total number of authors(2) correct
[TestMethod]
public void IsRepositoryAddsAuthor()
{
Author productToInsert = new Author
{
Auth_Id = 4,
First_Name = "Author FirstName 004",
Last_Name = "Author LastName 004",
Biography = "Author 4th Bio" };
Repo.AddAuthor(productToInsert);
// If Product inserts successfully,
//number of records will increase to 4
var result = Repo.GetAuthors();
var numberOfRecords = result.ToList().Count;
Assert.AreEqual(2, numberOfRecords);
}
#endregion #region Book // check valid number of book/s(1) existing in current DB
[TestMethod]
public void IsRepositoryInitalizeWithValidNumberOfData_Book()
{
var result = Repo.GetBooksWithAuthors();
Assert.IsNotNull(result);
var numberOfRecords = result.ToList().Count;
Assert.AreEqual(1, numberOfRecords);
} // check add book method working and total number of books(2) correct
[TestMethod]
public void IsRepositoryAddsBook()
{
Book productToInsert = new Book
{
Book_Id = 4,
Book_Title = "Book Title 004",
Price = 9.00M,
Edition = "4th Edition",
Author_Id = 1
};
Repo.AddBook(productToInsert);
// If Product inserts successfully,
//number of records will increase to 4
var result = Repo.GetBooks();
var numberOfRecords = result.ToList().Count;
Assert.AreEqual(2, numberOfRecords);
}
#endregion #region Books with Author // check valid number of book and author/s(1) existing in current DB
[TestMethod]
public void IsRepositoryInitalizeWithValidNumberOfData_BooksWithAuthor()
{
var result = Repo.GetBooksWithAuthors();
Assert.IsNotNull(result);
var numberOfRecords = result.ToList().Count;
Assert.AreEqual(1, numberOfRecords);
} #endregion
#region DropDowns // check valid number of author/s(1) listing in dropdown
[TestMethod]
public void IsRepositoryInitalizeWithValidNumberOfData_AuthorDropDown()
{
var result = Repo.GetAuthorsIdName();
Assert.IsNotNull(result);
var numberOfRecords = result.ToList().Count;
Assert.AreEqual(1, numberOfRecords);
}
#endregion
}
这里我只编写了几个测试用例,就像上面那样,在进入客户端之前,您可以为需要测试的所有方法编写测试用例。 5. 然后通过Test >在运行;所有的测试 如果所有测试都通过,您将在测试资源管理器中看到如下屏幕 , 在这个图书馆应用程序结束后。UnitTest项目的结构如下所示 ,,,,,,,,,,,,,,,,,,,,,,,, , 现在让我们在LibraryApp中以HTTP方法的形式发布被测试的方法。之前的项目 Steps for LibraryApp.WebAPI 1. 创建空c# Web api项目,命名为“ProjectName.WebAPI” 2. 通过右键单击该项目解决方案或使用包管理器控制台安装实体框架。 3.在web中添加connectionstring。配置文件像上面的项目 4.提供以下库的参考资料 ,,,,System.Data.Entity才能 ,,,,LibraryApp.Core才能 ,,,,, LibraryApp.Infrastructure 5. 在web中添加connectionstring。配置文件像上面的项目 6. 通过右键单击此项目的控制器文件夹,插入controllers BooksController.cs 选择“webspap2controller with actions, using Entity Framework” 选择数据上下文类现在,我们选择的是“LibraryContext”是我们在LibraryApp.Infrastructure中创建的。稍后,我们将改变这一点。 选择我们在LibraryApp.Core中创建的Model类 作为控制器名称,你可以在这里给出任何名称。 在上面的步骤之后,Apicontroller自动生成它的方法,如下所示,它是用强耦合构造来构建的。因为它正在初始化LibraryContext类。 BooksController.cs 隐藏,收缩,复制Code
public class BooksController : ApiController
{
private LibraryContext db = new LibraryContext(); // GET: api/Books public IQueryable<Book> GetBooks()
{
return db.Books;
} // GET: api/Books/5
[ResponseType(typeof(Book))]
public IHttpActionResult GetBook(int id)
{
Book book = db.Books.Find(id);
if (book == null)
{
return NotFound();
} return Ok(book);
} // PUT: api/Books/5
[ResponseType(typeof(void))]
public IHttpActionResult PutBook(int id, Book book)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
} if (id != book.Book_Id)
{
return BadRequest();
} db.Entry(book).State = EntityState.Modified; try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
if (!BookExists(id))
{
return NotFound();
}
else
{
throw;
}
} return StatusCode(HttpStatusCode.NoContent);
} // POST: api/Books
[ResponseType(typeof(Book))]
public IHttpActionResult PostBook(Book book)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
} db.Books.Add(book);
db.SaveChanges(); return CreatedAtRoute("DefaultApi", new { id = book.Book_Id }, book);
} // DELETE: api/Books/5
[ResponseType(typeof(Book))]
public IHttpActionResult DeleteBook(int id)
{
Book book = db.Books.Find(id);
if (book == null)
{
return NotFound();
} db.Books.Remove(book);
db.SaveChanges(); return Ok(book);
} protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
} private bool BookExists(int id)
{
return db.Books.Count(e => e.Book_Id == id) > 0;
}
}
由于我们在visual studio中使用脚手架,它是创建LibraryContext类的对象来执行我们的操作,但我们不希望在Web API项目中使用LibraryContext类,LibraryContext继承了DbContext,它属于System.Data。实体,它是实体框架的一个组件 如果我们在我们的MVC(客户端)项目中有任何实体框架,那么我们就直接紧密地结合了我们的UI和数据库技术。 但是在我们的案例中,如果我们使用LibraryContext,那么我们将在我们的Web API项目中使用component of Entity Framework,这是一个部分紧密耦合的场景,原因是,我们将Web API项目与MVC前端项目连接起来。 我们需要使我们的项目完全远离紧密耦合,以便执行我们的操作,我们在基础设施项目中已经有了库类,我们可以使用它。 我们需要改变上面的强耦合架构为松耦合架构,因此我们改变上面的代码,如下所示。 BooksController.cs 隐藏,收缩,复制Code
public class BooksController : ApiController
{
private LibraryRepository db = new LibraryRepository(); //// GET: api/Books
// we can fetch data as XML file via http://localhost:13793/api/Books URL
public IEnumerable<Book> GetBooks()
{
// Calling the Reopsitory project GetBooks method
return db.GetBooks();
} // GET: api/Books/5
// we can fetch data as XML file via http://localhost:13793/api/Books/{id} URL
[ResponseType(typeof(Book))]
public IHttpActionResult GetBook(int id)
{
// Calling the Reopsitory project FindBookById method
Book book = db.FindBookById(id);
if (book == null)
{
return NotFound();
} return Ok(book);
} //// PUT: api/Books/5
// we can perform edit book method
[ResponseType(typeof(void))]
public IHttpActionResult PutBook(int id, Book book)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
} if (id != book.Book_Id)
{
return BadRequest();
}
// Calling the Reopsitory project EditBook method
db.EditBook(book); return StatusCode(HttpStatusCode.NoContent);
} //// POST: api/Books/
// we can perform add book method
[ResponseType(typeof(Book))]
public IHttpActionResult PostBook(Book book)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
// Calling the Reopsitory project AddBook method
db.AddBook(book); return CreatedAtRoute("DefaultApi", new { id = book.Book_Id }, book);
} //// DELETE: api/Books//5
// we can perform delete book method
[ResponseType(typeof(Book))]
public IHttpActionResult DeleteBook(int id)
{
Book book = db.FindBookById(id);
if (book == null)
{
return NotFound();
}
// Calling the Reopsitory project RemoveBook method
db.RemoveBook(id); return Ok(book);
} protected override void Dispose(bool disposing)
{
if (disposing)
{
// db.Dispose();
}
base.Dispose(disposing);
} // we can fetch data as XML file via http://localhost:13793/api/Books/Editions URL
// Here we are sharing Book Editions Dropdown as web service URL
[Route("api/Books/Editions")]
public IEnumerable<Basic> GetEditionIdNameWebAPI()
{
// Calling the Reopsitory project GetEditionIdName method
return db.GetEditionIdName();
} }
如果我们运行上面的LibraryApp。WebAPI项目并在web浏览器中复制以下uri,我们将得到以下XML文件 GetBooks() HTTP方法http://localhost:13793/api/books , GetBook(int id) HTTP方法http://localhost:13793/api/Books/{id} 类似地,在上面的BooksController创建过程中,我们正在生成AuthorsController类和BooksWithAuthorsController AuthorsController.cs 隐藏,收缩,复制Code
public class AuthorsController : ApiController
{
private LibraryRepository db = new LibraryRepository(); // GET: api/Authors
// we can fetch data as XML file via http://localhost:13793/api/Authors URI
public IEnumerable<Author> GetAuthors()
{
// Calling the Reopsitory project GetAuthors method
return db.GetAuthors();
} // GET: api/Authors/5
// we can fetch data as XML file via http://localhost:13793/api/Authors/{id} URI
[ResponseType(typeof(Author))]
public IHttpActionResult GetAuthor(int id)
{
// Calling the Reopsitory project FindAuthorById method
Author author = db.FindAuthorById(id);
if (author == null)
{
return NotFound();
} return Ok(author);
} // PUT: api/Authors/5
// we can perform edit author method
[ResponseType(typeof(void))]
public IHttpActionResult PutAuthor(int id, Author author)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
} if (id != author.Auth_Id)
{
return BadRequest();
}
// Calling the Reopsitory project EditAuthor method
db.EditAuthor(author); return StatusCode(HttpStatusCode.NoContent);
} // POST: api/Authors
// we can perform add author method
[ResponseType(typeof(Author))]
public IHttpActionResult PostAuthor(Author author)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
// Calling the Reopsitory project AddAuthor method
db.AddAuthor(author); return CreatedAtRoute("DefaultApi", new { id = author.Auth_Id }, author);
} // DELETE: api/Authors/5
// we can perform delete author method
[ResponseType(typeof(Author))]
public IHttpActionResult DeleteAuthor(int id)
{
Author author = db.FindAuthorById(id);
if (author == null)
{
return NotFound();
}
// Calling the Reopsitory project RemoveAuthor method
db.RemoveAuthor(id); return Ok(author);
} protected override void Dispose(bool disposing)
{
if (disposing)
{
//db.Dispose();
}
base.Dispose(disposing);
} // GET: api/Authors
// we can fetch data as XML file via http://localhost:13793/api/Authors/all URI
// Here we are sharing author id and name Dropdown as web service URL
[Route("api/Authors/all")]
public IEnumerable<Basic> GetAuthorsIdName()
{
// Calling the Reopsitory project GetAuthorsIdName method
return db.GetAuthorsIdName();
} // GET: api/Authors
// we can fetch data as XML file via http://localhost:13793/api/Authors/EmploymentStatus URI
// Here we are sharing employee status Dropdown as web service URL
[Route("api/Authors/EmploymentStatus")]
public IEnumerable<Basic> GetEmplyeeStatusIdNameWebAPI()
{
// Calling the Reopsitory project GetEmplyeeStatusIdName method
return db.GetEmplyeeStatusIdName();
}
}
在[System.Web.Http.Route("api/ControllerName/AnyName")]的帮助下,我们可以为我们的方法创建定制的URI BooksWithAuthorsController.cs 隐藏,收缩,复制Code
public class BooksWithAuthorsController : ApiController
{
private LibraryRepository db = new LibraryRepository(); // GET: api/BooksWithAuthors
// we can fetch data as XML file via http://localhost:13793/api/BooksWithAuthors URI
public IEnumerable<BookWithAuthor> GetBookswithAuthors()
{
// Calling the Reopsitory project GetBooksWithAuthors method
return db.GetBooksWithAuthors();
} // GET: api/BooksWithAuthors/3
// we can fetch data as XML file via http://localhost:13793/api/BooksWithAuthors/{id} URI
[ResponseType(typeof(BookWithAuthor))]
public IHttpActionResult GetBooksWithAuthorsById(int id)
{
// Calling the Reopsitory project FindBooksWithAuthorsById method
BookWithAuthor bookwithauthor = db.FindBooksWithAuthorsById(id);
if (bookwithauthor == null)
{
return NotFound();
} return Ok(bookwithauthor);
} // GET: api/BooksWithAuthors/3/Price
// we can fetch data as XML file via http://localhost:13793/api/BooksWithAuthors/{id}/Price URI
[ResponseType(typeof(decimal))]
[System.Web.Http.Route("api/BooksWithAuthors/{id}/Price")]
public IHttpActionResult GetBooksPriceById(int? id)
{
// Calling the Reopsitory project findBookPrice method
decimal bookprice = db.findBookPrice(id); return Ok(bookprice);
} // GET: api/BooksWithAuthors/3/booktitle/Price
// http://localhost:13793/api/BooksWithAuthors/{id}/{book title}/Price URI
[ResponseType(typeof(decimal))]
[System.Web.Http.Route("api/BooksWithAuthors/{id}/{name}/Price")]
public IHttpActionResult GetBooksPriceById(int? id, string name = null)
{
// Calling the Reopsitory project findBookPrice method
decimal bookprice = db.findBookPrice(id,name); return Ok(bookprice);
}
}
上述GetBooksPriceById()方法的特性是,作为这些重载方法的响应,我们返回十进制值。 您将从中学到的另一件事是,如何配置重载可以发送多个参数的web方法。 GetBooksPriceById (int ?id), HTTP Method http://localhost: 13793 / api / BooksWithAuthors / {id} /价格 Getbookspricebyid (int ?HTTP方法 http://localhost: 13793 / api / bookswithauthors / {id} / {book_title} /价格 在这个Web服务项目结束时,每个GET方法,我们可以通过复制和检查我们的程序在浏览器上粘贴url,从数据库中获取的数据是否正确。 现在我们要移动到项目堆栈的最后一部分LibraryApp。MVC ASP。NET MVC 5客户端 Steps for LibraryApp.MVC 1. 创建空c# ASP。NET MVC 5项目,命名为“ProjectName.MVC” 2.在web中添加connectionstring。配置文件像上面的项目 3.提供下列图书馆的参考资料 ,,,,, System.Net.Http.Formatting ,,,,, System.Net.Http.Headers ,,,,, LibraryApp.Core ,,,,, LibraryApp.Infrastructure ,,,,LibraryApp.WebAPI才能 4. 现在在模型文件夹中添加新类为“LibraryClient.cs” 要制作MVC控制器,我们必须从我们的c#代码中调用上面的API。如果你在网上冲浪,你会看到在这个场景的大多数例子中,通过一个简单的AJAX调用使用jQuery。 但是我们可以使用HttpClient. 在这一节中,你将看到如何从MVC. Controller actions返回JSON调用WebAPI控制器端点。当你调用它们时,你会得到一个大字符串。然后你把这个字符串解析成MVC应用程序中的一个对象,这样就很好了。 所以让我们使用libraryclient文件来处理我们的HTTP方法,这些文件可以在MVC控制器中使用。 LibraryClient.cs 隐藏,收缩,复制Code
public class LibraryClient
{
//All the HTTP URI we are assigning here to ease of reuse
private string BOOKWITHAUTHOR_URI = "http://localhost:13793/api/BooksWithAuthors";
private string AUTHOR_URI = "http://localhost:13793/api/Authors";
private string BOOK_URI = "http://localhost:13793/api/Books"; #region //Books with Authors // Get all Book with Authors
public IEnumerable<BookWithAuthor> GetAllBookWithAuthors()
{
try
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(BOOKWITHAUTHOR_URI);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.GetAsync("BooksWithAuthors").Result;
if (response.IsSuccessStatusCode)
return response.Content.ReadAsAsync<IEnumerable<BookWithAuthor>>().Result; return null;
}
catch
{
return null;
}
} // Get a specific Book with Author
public BookWithAuthor GetBookwithAuthor(int id)
{
try
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(BOOKWITHAUTHOR_URI);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.GetAsync("BooksWithAuthors/" + id).Result;
if (response.IsSuccessStatusCode)
return response.Content.ReadAsAsync<BookWithAuthor>().Result; return null;
}
catch
{
return null;
}
} #endregion #region // Book //Get book details only public Book GetBook(int id)
{
try
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(BOOK_URI);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.GetAsync("Books/" + id).Result;
if (response.IsSuccessStatusCode)
return response.Content.ReadAsAsync<Book>().Result; return null;
}
catch
{
return null;
}
}
// Create a Book
public bool CreateBook(Book book)
{
try
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(BOOK_URI);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.PostAsJsonAsync("Books/", book).Result; return response.IsSuccessStatusCode;
}
catch
{
return false;
}
} // Edit a Book
public bool EditBook(Book book)
{
try
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(BOOK_URI);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.PutAsJsonAsync("Books/" + book.Book_Id, book).Result; return response.IsSuccessStatusCode;
}
catch
{
return false;
}
} // Delete a Book
public bool DeleteBook(int id)
{
try
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(BOOK_URI);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.DeleteAsync("Books/" + id).Result; return response.IsSuccessStatusCode;
}
catch
{
return false;
}
} #endregion #region // Author // Get All Authors
public IEnumerable<Author> GetAllAuthors()
{
try
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(AUTHOR_URI);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.GetAsync("Authors").Result;
if (response.IsSuccessStatusCode)
return response.Content.ReadAsAsync<IEnumerable<Author>>().Result; return null;
}
catch
{
return null;
}
} // Get a specific author
public Author GetAuthor(int id)
{
try
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(AUTHOR_URI);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.GetAsync("Authors/" + id).Result;
if (response.IsSuccessStatusCode)
return response.Content.ReadAsAsync<Author>().Result; return null;
}
catch
{
return null;
}
} //Create an author
public bool CreateAuthor(Author author)
{
try
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(AUTHOR_URI);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.PostAsJsonAsync("Authors/", author).Result; return response.IsSuccessStatusCode;
}
catch
{
return false;
}
} // Edit an author
public bool EditAuthor(Author author)
{
try
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(AUTHOR_URI);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.PutAsJsonAsync("Authors/" + author.Auth_Id, author).Result; return response.IsSuccessStatusCode;
}
catch
{
return false;
} } // Delete an author
public bool DeleteAuthr(int id)
{
try
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(AUTHOR_URI);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.DeleteAsync("Authors/" + id).Result; return response.IsSuccessStatusCode;
}
catch
{
return false;
} } //All the DropDown in this system
// Get all the authors id and name
public IEnumerable<Basic> GetAuthorsIdName()
{
try
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(AUTHOR_URI);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.GetAsync("Authors/all").Result;
if (response.IsSuccessStatusCode)
return response.Content.ReadAsAsync<IEnumerable<Basic>>().Result; return null;
}
catch
{
return null;
}
} //Get employee status id and name
public IEnumerable<Basic> GetEmplyeeStatusIdNameMVCModel()
{
try
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(AUTHOR_URI);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.GetAsync("Authors/EmploymentStatus").Result;
if (response.IsSuccessStatusCode)
return response.Content.ReadAsAsync<IEnumerable<Basic>>().Result;
return null;
}
catch
{
return null;
}
} //Get book editions id and name
public IEnumerable<Basic> GetEditionIdNameMVCModel()
{
try
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(AUTHOR_URI);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.GetAsync("Books/Editions").Result;
if (response.IsSuccessStatusCode)
return response.Content.ReadAsAsync<IEnumerable<Basic>>().Result;
return null;
}
catch
{
return null;
}
} #endregion }
现在我们可以很容易地在mvc控制器中重用上面的libraryclient方法,如下所示 BookWithAuthorController.cs 隐藏,复制Code
public class BookWithAuthorController : Controller
{
// GET: BooksWithAuthors
public ActionResult BookswithAuthors()
{
LibraryClient bwu = new LibraryClient();
ViewBag.listBookswithAuthors = bwu.GetAllBookWithAuthors();
return View();
}
}
BooksController.cs 隐藏,收缩,复制Code
public class BooksController : Controller
{
// GET: Books/Create
public ActionResult Create()
{
LibraryClient lc = new LibraryClient();
ViewBag.listAuthors = lc.GetAuthorsIdName().Select
(x => new SelectListItem
{ Value = x.ID.ToString(),
Text = x.NAME
});
ViewBag.listEditions = lc.GetEditionIdNameMVCModel().Select
(x => new SelectListItem
{ Value = x.NAME,
Text = x.NAME
});
return View();
} // POST: Books/Create
[HttpPost]
public ActionResult Create(Book book)
{
LibraryClient lc = new LibraryClient();
lc.CreateBook(book);
return RedirectToAction("BookswithAuthors", "BookWithAuthor");
} // GET: Books/Delete
public ActionResult Delete(int id)
{
LibraryClient lc = new LibraryClient();
lc.DeleteBook(id);
return RedirectToAction("BookswithAuthors", "BookWithAuthor");
} // GET: Books/Edit
[HttpGet]
public ActionResult Edit(int id)
{
LibraryClient lc = new LibraryClient();
Book book = new Book();
book = lc.GetBook(id);
ViewBag.listAuthors = lc.GetAuthorsIdName().Select
(x => new SelectListItem
{ Value = x.ID.ToString(),
Text = x.NAME
});
ViewBag.listEditions = lc.GetEditionIdNameMVCModel().Select
(x => new SelectListItem
{ Value = x.NAME,
Text = x.NAME
});
return View("Edit", book);
} // POST: Books/Edit
[HttpPost]
public ActionResult Edit(Book book)
{
LibraryClient pc = new LibraryClient();
pc.EditBook(book);
return RedirectToAction("BookswithAuthors", "BookWithAuthor");
}
}
要绑定下拉列表和ViewBag属性,我们可以遵循 1 st Approach 隐藏,复制Code
ViewBag.listAuthers = new SelectList(lc.GetAuthersIdName(), "ID", "Name")
2日Approach 隐藏,复制Code
ViewBag.listAuthers = lc.GetAuthersIdName().Select(x => new SelectListItem
{
Value = x.ID.ToString(),
Text = x.Name
});
AuthorsController.cs 隐藏,收缩,复制Code
public class AuthorsController : Controller
{
// GET: Authors
public ActionResult Index()
{
LibraryClient lc = new LibraryClient();
ViewBag.listAuthors = lc.GetAllAuthors(); return View();
} // GET: Authors/Create
public ActionResult Create()
{
LibraryClient lc = new LibraryClient();
ViewBag.listEmploymentStatus = lc.GetEmplyeeStatusIdNameMVCModel().Select
(x => new SelectListItem
{ Value = x.NAME,
Text = x.NAME
}); return View("Create"); } // POST: Authors/Create
[HttpPost]
public ActionResult Create(Author author)
{
LibraryClient lc = new LibraryClient();
lc.CreateAuthor(author); return RedirectToAction("Index", "Authors");
} // GET: Authors/Delete
public ActionResult Delete(int id)
{
LibraryClient lc = new LibraryClient();
lc.DeleteAuthr(id); return RedirectToAction("Index", "Authors");
} // GET: Authors/Edit
[HttpGet]
public ActionResult Edit(int id)
{
LibraryClient lc = new LibraryClient();
Author author = new Author();
ViewBag.listEmploymentStatus = lc.GetEmplyeeStatusIdNameMVCModel().Select
(x => new SelectListItem
{ Value = x.NAME,
Text = x.NAME
});
author = lc.GetAuthor(id); return View("Edit", author);
} // POST: Authors/Edit
[HttpPost]
public ActionResult Edit(Author author)
{
LibraryClient pc = new LibraryClient();
pc.EditAuthor(author);
return RedirectToAction("Index", "Authors");
}
}
包含作者的书籍列表在主仪表板上 隐藏,收缩,复制Code
@{
ViewBag.Title = "Books with Authors";
Layout = "~/Views/Shared/_Layout.cshtml";
} <h4>Books with Authors</h4> <p>
<buttontype="button"class="btn btn-primary btn-sm"onclick="location.href='@Url.Action("Create","Books")';"><spanclass="glyphicon glyphicon-plus"></span> Create New Book</button>
<buttontype="button"class="btn btn-primary btn-sm"onclick="location.href='@Url.Action("Index","Authors")';"><spanclass="glyphicon glyphicon-user"></span> Authors List</button>
</p> <tableclass="table">
<tr>
<th>
Book ID
</th>
<th>
Book Title
</th>
<th>
Author Name
</th>
<th>
Edition
</th>
<th>
Price
</th>
<th>
Actions
</th>
</tr> @foreach (var item in ViewBag.listBookswithAuthors)
{
<tr>
<td>
@item.BookWithAuthor_Id
</td>
<td>
@item.BookWithAuthor_Title </td>
<td>
@item.BookWithAuthor_AuthorName
</td>
<td>
@item.Edition
</td>
<td>
@item.Price
</td> <td>
<aclass="btn btn-danger btn-xs"onclick="return confirm('Are you Sure ?')"href="@Url.Action("Delete","Books",new{id= item.BookWithAuthor_Id })"><spanclass="glyphicon glyphicon-trash"></span> Delete Book</a>
<aclass="btn btn-warning btn-xs"href="@Url.Action("Edit","Books",new{id= item.BookWithAuthor_Id })"><spanclass="glyphicon glyphicon-scissors"></span> Edit Book</a>
</td>
</tr>
} </table>
创建一个书 隐藏,收缩,复制Code
@model LibraryApp.Core.Entities.Book @{
ViewBag.Title = "Create";
Layout = "~/Views/Shared/_Layout.cshtml";
} <h4>Create a Book</h4> @using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<divclass="form-horizontal"> <hr/>
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<divclass="form-group">
@Html.LabelFor(model => model.Book_Title, htmlAttributes: new { @class = "control-label col-md-2" })
<divclass="col-md-10">
@Html.EditorFor(model => model.Book_Title, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Book_Title, "", new { @class = "text-danger" })
</div>
</div> <divclass="form-group">
@Html.LabelFor(model => model.Price, htmlAttributes: new { @class = "control-label col-md-2" })
<divclass="col-md-10">
@Html.EditorFor(model => model.Price, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Price, "", new { @class = "text-danger" })
</div>
</div> <divclass="form-group">
@Html.LabelFor(model => model.Edition, htmlAttributes: new { @class = "control-label col-md-2" })
<divclass="col-md-10">
@Html.DropDownList("Edition", (IEnumerable<SelectListItem>)ViewBag.listEditions, "Select the Edition", htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.Edition, "", new { @class = "text-danger" })
</div>
</div> <divclass="form-group">
@Html.LabelFor(model => model.Author_Id, "Author Name", htmlAttributes: new { @class = "control-label col-md-2" })
<divclass="col-md-10">
@*Non Strongly Type*@
@Html.DropDownList("Author_Id", (IEnumerable<SelectListItem>)ViewBag.listAuthors, "Select the author name", htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.Author_Id, "", new { @class = "text-danger" })
</div>
</div> <divclass="form-group">
<divclass="col-md-offset-2 col-md-10">
<inputtype="submit"value="Create"class="btn btn-default"/>
</div>
</div>
</div>
} <div>
<p>
<buttontype="button"class="btn btn-primary btn-sm"onclick="location.href='@Url.Action("BookswithAuthors","BookWithAuthor")';"><spanclass="glyphicon glyphicon-list-alt"></span> Book List</button>
</p>
</div>
如果你注意到这里,上面创建了Book view类,它将其下拉列表与非强类型方法绑定 非强类型方法 隐藏,复制Code
@Html.DropDownList("Author_Id", (IEnumerable<SelectListItem>)ViewBag.listAuthors, "Select the author name", htmlAttributes: new { @class = "form-control" })
强类型的方法 隐藏,复制Code
@Html.DropDownList(m => m.Auther_Id, (IEnumerable<SelectListItem>)ViewBag.listAuthers, "Select the author name", htmlAttributes: new { @class = "form-control" })
编辑一本书 隐藏,收缩,复制Code
@model LibraryApp.Core.Entities.Book @{
ViewBag.Title = "Edit";
Layout = "~/Views/Shared/_Layout.cshtml";
} <h4>Edit Book</h4> @using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<divclass="form-horizontal">
<hr/>
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.HiddenFor(model => model.Book_Id) <divclass="form-group">
@Html.LabelFor(model => model.Book_Title, htmlAttributes: new { @class = "control-label col-md-2" })
<divclass="col-md-10">
@Html.EditorFor(model => model.Book_Title, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Book_Title, "", new { @class = "text-danger" })
</div>
</div> <divclass="form-group">
@Html.LabelFor(model => model.Price, htmlAttributes: new { @class = "control-label col-md-2" })
<divclass="col-md-10">
@Html.EditorFor(model => model.Price, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Price, "", new { @class = "text-danger" })
</div>
</div> <divclass="form-group">
@Html.LabelFor(model => model.Edition, htmlAttributes: new { @class = "control-label col-md-2" })
<divclass="col-md-10">
@*@Html.EditorFor(model => model.Edition, new { htmlAttributes = new { @class = "form-control" } })*@
@Html.DropDownList("Edition", (IEnumerable<SelectListItem>)ViewBag.listEditions, "Select the Edition", htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.Edition, "", new { @class = "text-danger" })
</div>
</div> <divclass="form-group">
@Html.LabelFor(model => model.Author_Id, "Author Name", htmlAttributes: new { @class = "control-label col-md-2" })
<divclass="col-md-10">
@*Non Strongly Type*@
@Html.DropDownList("Author_Id", (IEnumerable<SelectListItem>)ViewBag.listAuthors, "Select the author name", htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.Author_Id, "", new { @class = "text-danger" })
</div>
</div> <divclass="form-group">
<divclass="col-md-offset-2 col-md-10">
<inputtype="submit"value="Save"class="btn btn-default"/>
</div>
</div>
</div>
} <div>
<p>
<buttontype="button"class="btn btn-primary btn-xs"onclick="location.href='@Url.Action("BookswithAuthors","BookWithAuthor")';">Back to List</button>
</p>
</div>
作者List 仪表板 隐藏,收缩,复制Code
@{
ViewBag.Title = "Authors";
Layout = "~/Views/Shared/_Layout.cshtml";
} <h4> All Authors</h4> <p>
<buttontype="button"class="btn btn-primary btn-sm"onclick="location.href='@Url.Action("BookswithAuthors","BookWithAuthor")';"><spanclass="glyphicon glyphicon-list-alt"></span> Book List</button>
<buttontype="button"class="btn btn-primary btn-sm"onclick="location.href='@Url.Action("Create","Authors")';"><spanclass="glyphicon glyphicon-plus"></span> Create an Author</button>
</p> <tableclass="table">
<tr>
<th>
ID
</th>
<th>
First Name
</th>
<th>
Last Name
</th>
<th>
Biography
</th>
<th>
Employed
</th>
<th>
Action
</th>
</tr> @foreach (var item in ViewBag.listAuthors)
{
<tr>
<td>
@item.Auth_Id
</td>
<td>
@item.First_Name </td>
<td>
@item.Last_Name
</td>
<td>
@item.Biography
</td>
<td>
@if (item.IsEmployed == "Y")
{ <p><spanclass="glyphicon glyphicon-ok"style="color:lime"></span></p>
} @if (item.IsEmployed == "N")
{
<p><spanclass="glyphicon glyphicon-remove"style="color:deeppink"></span></p>
} </td> <td>
<aclass="btn btn-danger btn-xs"onclick="return confirm('Are you Sure ?')"href="@Url.Action("Delete","Authors",new{id= item.Auth_Id })"><spanclass="glyphicon glyphicon-trash"></span> Delete Author</a>
<aclass="btn btn-warning btn-xs"href="@Url.Action("Edit","Authors",new{id= item.Auth_Id })"><spanclass="glyphicon glyphicon-scissors"></span> Edit Author</a>
</td>
</tr>
} </table>
创建一个作者 隐藏,收缩,复制Code
@model LibraryApp.Core.Entities.Author @{
ViewBag.Title = "Create";
Layout = "~/Views/Shared/_Layout.cshtml";
} <h4>Create an Author</h4> @using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<divclass="form-horizontal"> <hr/>
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<divclass="form-group">
@Html.LabelFor(model => model.First_Name, htmlAttributes: new { @class = "control-label col-md-2" })
<divclass="col-md-10">
@Html.EditorFor(model => model.First_Name, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.First_Name, "", new { @class = "text-danger" })
</div>
</div> <divclass="form-group">
@Html.LabelFor(model => model.Last_Name, htmlAttributes: new { @class = "control-label col-md-2" })
<divclass="col-md-10">
@Html.EditorFor(model => model.Last_Name, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Last_Name, "", new { @class = "text-danger" })
</div>
</div> <divclass="form-group">
@Html.LabelFor(model => model.Biography, htmlAttributes: new { @class = "control-label col-md-2" })
<divclass="col-md-10">
@Html.EditorFor(model => model.Biography, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Biography, "", new { @class = "text-danger" })
</div>
</div> <divclass="form-group">
@Html.LabelFor(model => model.IsEmployed, "Employed", htmlAttributes: new { @class = "control-label col-md-2" })
<divclass="col-md-10">
@Html.DropDownList("IsEmployed", (IEnumerable<SelectListItem>)ViewBag.listEmploymentStatus, "Select the Employment Status", htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.IsEmployed, "", new { @class = "text-danger" })
</div>
</div> <divclass="form-group">
<divclass="col-md-offset-2 col-md-10">
<inputtype="submit"value="Create"class="btn btn-default"/>
</div>
</div>
</div>
} <div>
<p>
<buttontype="button"class="btn btn-primary btn-sm"onclick="location.href='@Url.Action("Index","Authors")';"><spanclass="glyphicon glyphicon-user"></span> Authors List</button>
</p>
</div>
编辑一个作者 隐藏,收缩,复制Code
@model LibraryApp.Core.Entities.Author @{
ViewBag.Title = "Edit";
Layout = "~/Views/Shared/_Layout.cshtml";
} <h4>Edit Author</h4> @using (Html.BeginForm())
{
@Html.AntiForgeryToken()
<divclass="form-horizontal">
<hr/>
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.HiddenFor(model => model.Auth_Id) <divclass="form-group">
@Html.LabelFor(model => model.First_Name, htmlAttributes: new { @class = "control-label col-md-2" })
<divclass="col-md-10">
@Html.EditorFor(model => model.First_Name, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.First_Name, "", new { @class = "text-danger" })
</div>
</div> <divclass="form-group">
@Html.LabelFor(model => model.Last_Name, htmlAttributes: new { @class = "control-label col-md-2" })
<divclass="col-md-10">
@Html.EditorFor(model => model.Last_Name, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Last_Name, "", new { @class = "text-danger" })
</div>
</div> <divclass="form-group">
@Html.LabelFor(model => model.Biography, htmlAttributes: new { @class = "control-label col-md-2" })
<divclass="col-md-10">
@Html.EditorFor(model => model.Biography, new { htmlAttributes = new { @class = "form-control" } })
@Html.ValidationMessageFor(model => model.Biography, "", new { @class = "text-danger" })
</div>
</div> <divclass="form-group">
@Html.LabelFor(model => model.IsEmployed,"Employed", htmlAttributes: new { @class = "control-label col-md-2" })
<divclass="col-md-10">
@Html.DropDownList("IsEmployed", (IEnumerable<SelectListItem>)ViewBag.listEmploymentStatus, "Select the Employment Status", htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.IsEmployed, "", new { @class = "text-danger" })
</div>
</div> <divclass="form-group">
<divclass="col-md-offset-2 col-md-10">
<inputtype="submit"value="Save"class="btn btn-default"/>
</div>
</div>
</div>
} <div>
<p>
<buttontype="button"class="btn btn-primary btn-sm"onclick="location.href='@Url.Action("Index","Authors")';"><spanclass="glyphicon glyphicon-user"></span> Authors List</button>
</p>
</div>
下面的GitHub位置包含了本示例簿记解决方案应用程序的完整源代码。SQL脚本不需要包含,因为它是用代码优先的方法构建的。所以你可以很容易地开发这个。 如果在开发过程中发现任何错误或问题,请随时发表评论。您的建议对我来说很重要,因为我还处于初级发展阶段。 在这里可以找到最初的帖子。 参考文献 CodeProject -代码优先方法使用实体框架4.1,反转控制,统一框架,存储库工作单元模式和MVC3剃须刀视图 CodeProject—使用MVC中的存储库模式进行CRUD操作 如何在ASP中实现存储库模式。净MVC应用程序 碎片管理-创建一个ASP。NET Web API使用实体框架代码优先方法和存储库模式 levelnis.co。如何调用一个Web API端点没有使用JavaScript? 本文转载于:http://www.diyabc.com/frontweb/news19804.html
结合实体框架(代码优先)、工作单元测试、Web API、ASP. net等,以存储库设计模式开发示例项目。NET MVC 5和引导的更多相关文章
- ASP.NET Core 2.1 Web API + Identity Server 4 + Angular 6 + Angular Material 实战小项目视频
视频简介 ASP.NET Core Web API + Angular 6的教学视频 我是后端开发人员, 前端的Angular部分讲的比较差一些, 可以直接看代码!!!! 这是一个小项目的实战视频, ...
- 代码演示用 KnockoutJS 和 Web API 对一个表格(Gird)进行 CRUD 操作,在 MVC 5 下
实体类: using System; using System.Collections.Generic; public partial class EmployeeInfo { public int ...
- 通过C#代码调用Dynamics 365 Web API执行批量操作
我是微软Dynamics 365 & Power Platform方面的工程师罗勇,也是2015年7月到2018年6月连续三年Dynamics CRM/Business Solutions方面 ...
- 使用MVC 5、Web API 2、KnockoutJS、Ninject和NUnit开发、架构和测试Web应用程序
做一名微软软件开发人员就像在国际煎饼屋订早餐一样.每道菜都有一堆煎饼,你必须从各种各样的煎饼和糖浆口味中选择.对于web应用程序,解决方案堆栈是一组软件子系统或组件,用于交付功能完整的解决方案(无论是 ...
- ASP.NET Web API - ASP.NET MVC 4 系列
Web API 项目是 Windows 通信接口(Windows Communication Foundation,WCF)团队及其用户激情下的产物,他们想与 HTTP 深度整合.WCF ...
- Asp.Net Web Api 2 实现多文件打包并下载文件示例源码_转
一篇关于Asp.Net Web Api下载文件的文章,之前我也写过类似的文章,请见:<ASP.NET(C#) Web Api通过文件流下载文件到本地实例>本文以这篇文章的基础,提供了Byt ...
- C# CodeFirst(EF框架)代码优先创建数据库
namespace WebEF.Model{ public class ModelContext:DbContext //继承DBcontext 来自EF框架 { public ModelContex ...
- ABP框架 - 我的第一个Web API
本文示例源代码地址https://github.com/lcyhjx/abp-training 上一篇我们已经对ABP是什么,能做什么.有了一个印象.那么接下来我们将动手使用ABP框架快速开发一个AP ...
- YoyoGo微服务框架入门系列-快速编写WEB API
前言 YoyoGo是一个使用Golang编写的一个简单.轻量.快速.基于依赖注入的微服务框架,目前依然在研发阶段,欢迎Star以及一起参与到框架的研发 GitHub地址:https://github. ...
随机推荐
- maven踩过的坑
maven配置 maven默认配置 解决每次打开idea的spring项目都需要重新配置maven,选择file/other settings/preference for new projects ...
- 持续部署入门:基于 Kubernetes 实现滚动发布
前言 软件世界比以往任何时候都更快.为了保持竞争力,需要尽快推出新的软件版本,而不会中断活跃用户访问,影响用户体验.越来越多企业已将其应用迁移到 Kubernetes. 在 Kubernetes 中有 ...
- Oracle WITH 语句 语法
With语句可以在查询中做成一个临时表/View,用意是在接下来的SQL中重用,而不需再写一遍. With Clause方法的优点: 增加了SQL的易读性,如果构造了多个子查询,结构会更清晰. 示例: ...
- 高德地图POI爬取_Python
高德地图POI 官方文档:https://lbs.amap.com/api/webservice/guide/api/search#introduce 官网控制台:https://lbs.amap.c ...
- leetcode刷题-51N皇后
题目 n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击. 给定一个整数 n,返回所有不同的 n 皇后问题的解决方案. 每一种解法包含一个明确的 n 皇后问 ...
- Python 字符串去除相邻重复的元素
1 def quchong(S): 2 str1=[""] 3 for i in S: 4 if i == str1[-1]: 5 str1.pop() 6 else: 7 str ...
- delphi DBgrid应用全书
在一个Dbgrid中显示多数据库 在数据库编程中,不必要也不可能将应用程序操作的所有数据库字段放入一个数据库文件中.正确的数据库结构应是:将数据库字段放入多个数据库文件,相关的数据库都包含一个唯 ...
- JZOJ1496 页
Description 战神阿瑞斯听说2008年在中华大地上,将举行一届规模盛大的奥林匹克运动会,心中顿觉异常兴奋,他想让天马在广阔的天空上,举行一场精彩的天马队列变换表演.首先,战神安排n头高度不同 ...
- [LeetCode]394. 字符串解码(栈)
题目 给定一个经过编码的字符串,返回它解码后的字符串. 编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次.注意 k 保证为正整数. ...
- Node.js使用npm安装模块太慢,解决办法
转自 淘宝 npm 地址: http://npm.taobao.org/ 如何使用 有很多方法来配置npm的registry地址,下面根据不同情境列出几种比较常用的方法.以淘宝npm镜像举例: 1.临 ...