Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use MVC Framework to build Project structure

2025-02-14 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article is about how to use the MVC framework to build the project structure, the editor thinks it is very practical, so I share it with you to learn. I hope you can get something after reading this article.

I. Preface

The following will use code to explain each level one by one. Because you want to build a basic and complete structure, the article may be relatively long. In addition, for practical purposes, it is not strictly in accordance with the traditional three-tier as a very clear level of function division.

II. Description of requirements

To facilitate your understanding, it will be explained by a small system for account management. The specific requirements are as follows:

User information is divided into main information and extended information, a user can have (or not) a user extended information.

Record a user's login record. A user can have multiple login records, but the login record belongs to a unique user.

A user can have multiple roles, and a role can be assigned to multiple users.

III. Architectural basis

(1) function return value

For an operational business function (such as add, modify, delete), we usually deal with the return value by using simple types, and there are usually the following scenarios:

Return void directly, that is, nothing is returned, and an exception is thrown during the operation. As long as there is no exception thrown, the operation is considered successful.

Returns the return value of the bool type of whether the operation is successful or not

Return the new data information after the operation has changed

Returns the return value of the status code representing various results

Returns a custom enumeration to represent the various results of the operation

If you want to return more than one value, use out to add the return parameter

What's wrong with this? let's analyze it one by one:

The operation of the system is terminated by throwing exceptions, which are thrown up the call stack layer by layer, which will cause great performance problems.

The bool value is too rigid to represent various situations in the business operation.

Return the changed data and judge whether the operation is successful or not with the original data.

The problem of 2 is solved with status codes, but the maintenance cost of various status codes will also be very high.

The problem of translation is solved programmatically by using enumerated values, but it is still necessary to translate enumerated values into textual descriptions of various situations.

To sum up, what kind of business operation result do we need?

To be able to indicate the success or failure of the operation (nonsense)

It is necessary to be able to express various operation scenarios quickly (such as parameter errors, query data does not exist, data status does not meet the operation requirements, etc.)

Can return additional return information (for example, if there is a follow-up operation after the update is successful, you need to use the updated value)

It is best to use uniform code for return value processing in the caller.

It is best to customize the returned text description information

It is best to separate the information returned to the user from the logging information

To sum up, it is obvious that the return value of a simple type can not meet the requirements, so you need to define a return value class specifically used to encapsulate the return value information, as defined here:

/ Business operation result information class Encapsulate the operation result / public class OperationResult {# region constructor / initialize a new instance of the business operation result information class / Business operation result type public OperationResult (OperationResultType resultType) {ResultType = resultType } / initialize a new instance of the business operation result information class that defines the return message / business operation result type / business return message public OperationResult (OperationResultType resultType String message): this (resultType) {Message = message } / initialize a new instance of the business operation result information class that defines the return message and additional data / business operation result type / business return message / business return data public OperationResult (OperationResultType resultType String message, object appendData): this (resultType, message) {AppendData = appendData } / / initialize a new instance of the business operation result information class that defines the return message and log message / business operation result type / / business return message / business log record Message public OperationResult (OperationResultType resultType String message, string logMessage): this (resultType, message) {LogMessage = logMessage } / / initialize a definition return message, New instance of business operation result information class of log message and additional data / business operation result type / / business return message / / business log recording message / / business return data public OperationResult (OperationResultType resultType String message, string logMessage, object appendData): this (resultType, message, logMessage) {AppendData = appendData } # endregion # region attribute / get or set the operation result type / public OperationResultType ResultType {get; set } / get or set the information returned by the operation / public string Message {get; set;} / get or set the log message returned by the operation, which is used to record the log / public string LogMessage {get; set } / get or set additional information about the operation result / public object AppendData {get; set;} # endregion}

Then define an enumeration that represents the results of the business operation, and there is a DescriptionAttribute feature on the enumeration entry, which is used as the description of the returned result when the above Message is empty.

/ enumeration of business operation results / [Description ("enumeration of business operation results")] public enum OperationResultType {/ Operation succeeded / [Description (")] Success, / / cancel the operation or the operation did not cause any changes / [Description ("the operation did not cause any changes, submit cancellation.")] NoChanged, / Parameter error / [Description ("Parameter error.")] ParamError, / / data for the specified parameter does not exist / [Description ("data for the specified parameter does not exist.")] QueryNull, / insufficient permissions / / [Description ("the current user has insufficient privileges to continue.")] PurviewLack, / illegal operation / [Description ("illegal operation.")] IllegalOperation, / warning / / [Description ("warning")] Warning, / the operation causes an error / [Description ("the operation causes an error.")] Error,}

(II) entity base class

For business entities, it is always necessary to have the same and necessary information, such as the creation time of the information; for example, if you want the database to have a "recycle bin" function to buffer data deletion, or a lot of data does not want to be completely deleted from the database, but only temporarily "disabled", it is also necessary to add a logically deleted tag. In addition, we want to impose a type qualification on all entity data warehousing operations to prevent the introduction of other non-entity types. For the above reasons, you have the following entity base class:

The base class of the domain model that can be persisted to the database. / / [Serializable] public abstract class Entity {# region constructor / data entity base class / protected Entity () {IsDeleted = false; AddDate = DateTime.Now } # endregion # region attribute / gets or sets whether the acquisition or setting is disabled, logical deletion, non-physical deletion / public bool IsDeleted {get; set } / get or set the add time / [DataType (DataType.DateTime)] public DateTime AddDate {get; set } / get or set the version control identity to handle concurrency / [ConcurrencyCheck] 1621913756 public byte [] Timestamp {get; set;} # endregion}

To add here, the original entity base class can be defined to represent the "entity number" of the Id attribute, but there is a problem, if defined, it limits the data type of the Id attribute, but the actual needs of some entities may use self-increasing int type, some entities use the guid type that is easy to merge data, so for flexibility and convenience, do not limit the data type of Id here.

IV. Architecture layering

The specific architectural layering is shown in the following figure:

(1) Core business layer

According to the requirements defined in the requirements description, for simplicity, only a simple user login function is implemented:

User information entity:

/ entity class-- user information / [Description ("user information")] public class Member: Entity {/ get or set the user number / public int Id {get; set } / get or set the user name / [Required] [StringLength (20)] public string UserName {get; set } / get or set the password / [Required] [StringLength (32)] public string Password {get; set } / get or set the user nickname / [Required] [StringLength (20)] public string NickName {get; set } / get or set user mailbox / [Required] [StringLength (50)] public string Email {get; set;} / get or set user extension information / public virtual MemberExtend Extend {get Set;} / get or set the user-owned role information collection / public virtual ICollection Roles {get; set;} / get or set the user login record collection / public virtual ICollection LoginLogs {get; set;}}

Core business contract: note that the return value of the interface uses the return value class defined above

/ account module core business contract / public interface IAccountContract {/ user login / login information / business operation result OperationResult Login (LoginInfo loginInfo);}

Core business implementation: the core business implementation class is an abstract class. Because there is no data access function, a Members field is used as the data source. The implementation of the business function is a virtual method, which can be rewritten in the corresponding derived class of the specific client (website, desktop, mobile) if necessary. Please pay attention to the processing of the return value in the specific implementation. Login here is only responsible for the core login business operations, and does not involve operations such as Http context state.

/ public abstract class AccountService: IAccountContract {private static readonly Member [] Members = new [] {new Member {UserName = "admin", Password = "123456", Email = "admin@gmfcn.net", NickName = "administrator"}, new Member {UserName = "gmfcn", Password = "123456" Email = "mf.guo@qq.com", NickName = "Guo Mingfeng"}} Private static readonly List LoginLogs = new List (); / user login / login information / business operation result public virtual OperationResult Login (LoginInfo loginInfo) {PublicHelper.CheckArgument (loginInfo, "loginInfo") Member member = Members.SingleOrDefault (m = > m.UserName = = loginInfo.Access | | m.Email = = loginInfo.Access); if (member = = null) {return new OperationResult (OperationResultType.QueryNull, "the user for the specified account does not exist.") ;} if (member.Password! = loginInfo.Password) {return new OperationResult (OperationResultType.Warning, "incorrect login password.") ;} LoginLog loginLog = new LoginLog {IpAddress = loginInfo.IpAddress, Member = member}; LoginLogs.Add (loginLog); return new OperationResult (OperationResultType.Success, "login succeeded." , member);}}

(2) site business layer

Site business contract: the site business contract inherits the core business contract and can have the business functions defined by the core layer. Site login authentication uses Forms's Cookie authentication, and the exit here does not involve the operation of the core layer, so the core layer does not have the exit function.

/ / account module site business contract / public interface IAccountSiteContract: IAccountContract {/ user login / login model information / business operation result OperationResult Login (LoginModel model) / user exits / void Logout ();}

Site business implementation: the site business implementation inherits the core business implementation and the site business contract, is responsible for converting the view model information received from UI into parameters defined by the core layer, and handles Session,Cookie and other Http related businesses related to the state of the website.

/ account module site business implementation / public class AccountSiteService: AccountService IAccountSiteContract {/ user login / / login model information / business operation result public OperationResult Login (LoginModel model) {PublicHelper.CheckArgument (model, "model") LoginInfo loginInfo = new LoginInfo {Access = model.Account, Password = model.Password, IpAddress = HttpContext.Current.Request.UserHostAddress}; OperationResult result = base.Login (loginInfo) If (result.ResultType = = OperationResultType.Success) {Member member = (Member) result.AppendData; DateTime expiration = model.IsRememberLogin? DateTime.Now.AddDays (7): DateTime.Now.Add (FormsAuthentication.Timeout); FormsAuthenticationTicket ticket = new FormsAuthenticationTicket (1, member.UserName, DateTime.Now, expiration, true, member.NickName, FormsAuthentication.FormsCookiePath); HttpCookie cookie = new HttpCookie (FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt (ticket)) If (model.IsRememberLogin) {cookie.Expires = DateTime.Now.AddDays (7);} HttpContext.Current.Response.Cookies.Set (cookie); result.AppendData = null;} return result } / user exits / public void Logout () {FormsAuthentication.SignOut ();}}

(3) site presentation layer

MVC controller: Action provides a uniform style of code to process the business operation result OperationResult

Public class AccountController: Controller {public AccountController () {AccountContract = new AccountSiteService ();} # region attribute public IAccountSiteContract AccountContract {get; set } # endregion # region View function public ActionResult Login () {string returnUrl = Request.Params ["returnUrl"]; returnUrl = returnUrl? Url.Action ("Index", "Home", new {area = ""}); LoginModel model = new LoginModel {ReturnUrl = returnUrl}; return View (model) } [HttpPost] public ActionResult Login (LoginModel model) {try {OperationResult result = AccountContract.Login (model); string msg = result.Message? Result.ResultType.ToDescription (); if (result.ResultType = = OperationResultType.Success) {return Redirect (model.ReturnUrl);} ModelState.AddModelError (", msg); return View (model) } catch (Exception e) {ModelState.AddModelError ("", e.Message); return View (model);}} public ActionResult Logout () {string returnUrl = Request.Params ["returnUrl"] ReturnUrl = returnUrl? Url.Action ("Index", "Home", new {area = ""}); if (User.Identity.IsAuthenticated) {AccountContract.Logout ();} return Redirect (returnUrl);} # endregion}

MVC view:

@ model GMF.Demo.Site.Models.LoginModel @ {ViewBag.Title = "Login"; Layout = "~ / Views/Shared/_Layout.cshtml" Login @ using (Html.BeginForm ()) {@ Html.AntiForgeryToken () @ Html.ValidationSummary (true) LoginModel @ Html.LabelFor (model = > model.Account) @ Html.EditorFor (model = > model.Account) @ Html.ValidationMessageFor (model = > model.Account) Html.LabelFor (model = > model.Password) @ Html.EditorFor (model = > model.Password) @ Html.ValidationMessageFor (model = > model.Password) @ Html.LabelFor (model = > model.IsRememberLogin) @ Html.EditorFor (model = > model) .IsRememberLogin) @ Html.ValidationMessageFor (model = > model.IsRememberLogin) @ Html.HiddenFor (m = > m.ReturnUrl)

} @ Html.ActionLink ("Back to List", "Index", "Home") @ section Scripts {@ Scripts.Render ("~ / bundles/jqueryval")}

At this point, the architecture of the whole project is completed, and the running results are as follows:

The above is how to use the MVC framework to build the project structure, the editor believes that there are some knowledge points that we may see or use in our daily work. I hope you can learn more from this article. For more details, please follow the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report