上篇我们看了登陆界面,本篇我对服务端进行一个剖析。以及主界面的设计。我们上次忘记解释一个Silverlight的项目如何寄宿在MVC项目上。我们先来看看如何寄宿。看下图
我们看到了MISInfoManage这个项目是一个Silverlight项目。它寄宿在MISInfomanage.Web.Host这个MVC3项目中。流程是这样的,Silverlight寄宿在MISInfomanage.Web.Host上,MISInfomanage.Web.Host这个项目它的启动路径如下图所示,是Home/Index,完整路径就是Http://localhost:port/Home/Index。
我们来看看控制器代码
当项目运行起来后,直接将页面导航至Index.chtml。所以到这里大家应该能想来Silverlight就寄宿在这个界面上。我们看看代码是如何寄宿的。
- @{
- Layout = null;
- }
- <!DOCTYPE html>
- <html>
- <head>
- <title>Index1</title>
- <style type="text/css">
- html, body
- {
- height: 100%;
- overflow: auto;
- }
- body
- {
- padding: 0;
- margin: 0;
- }
- #silverlightControlHost
- {
- height: 100%;
- text-align: center;
- }
- </style>
- <script type="text/javascript" src="../../Silverlight.js"></script>
- <script type="text/javascript">
- function onSilverlightError(sender, args) {
- var appSource = "";
- if (sender != null && sender != 0) {
- appSource = sender.getHost().source;
- }
- var errorType = args.ErrorType;
- var iErrorCode = args.ErrorCode;
- if (errorType == "ImageError" || errorType == "MediaError") {
- return;
- }
- var errMsg = "Silverlight 应用程序中未处理的错误 " + appSource + "\n";
- errMsg += "代码: " + iErrorCode + " \n";
- errMsg += "类别: " + errorType + " \n";
- errMsg += "消息: " + args.ErrorMessage + " \n";
- if (errorType == "ParserError") {
- errMsg += "文件: " + args.xamlFile + " \n";
- errMsg += "行: " + args.lineNumber + " \n";
- errMsg += "位置: " + args.charPosition + " \n";
- }
- else if (errorType == "RuntimeError") {
- if (args.lineNumber != 0) {
- errMsg += "行: " + args.lineNumber + " \n";
- errMsg += "位置: " + args.charPosition + " \n";
- }
- errMsg += "方法名称: " + args.methodName + " \n";
- }
- 引发新错误(errMsg);
- }
- </script>
- </head>
- <body>
- <form id="form1" runat="server" style="height: 100%">
- <div id="silverlightControlHost">
- <object data="data:application/x-silverlight-2," type="application/x-silverlight-2"
- width="100%" height="100%">
- <param name="source" value="/ClientBin/MISInfoManage.xap" />
- <param name="onError" value="onSilverlightError" />
- <param name="background" value="white" />
- <param name="minRuntimeVersion" value="4.0.50826.0" />
- <param name="autoUpgrade" value="true" />
- <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=4.0.50826.0" style="text-decoration: none">
- <img src="http://go.microsoft.com/fwlink/?LinkId=161376" alt="获取 Microsoft Silverlight"
- style="border-style: none" />
- </a>
- </object>
- </div>
- </form>
- </body>
- </html>
关键就在于Silverlight.js的引用,以及object中param的设置。在这里需要注意的是这个source属性,它的value值是指xap包所在的位置,如下所示,位于ClientBin下。
光凭这些代码还不能完成寄宿,我们还需要在MISInfomanage.Web.Host上点击右键,选择Silverlight Applications。添加要寄宿的Silverlight项目,如下
OK,这样就完成了一个Silverlight项目的寄宿。谈完这个,我们再回到Server端机构的解析,我就以一个登陆流程来解释。首先用户在登录界面点击登陆按钮,调用Login/GetUser/{id}。
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- using System.Web.Mvc;
- namespace MISInfoManage.Web.Controllers
- {
- using Server.Business.Interface;
- using Server.Domain;
- using Server.Model.edmx;
- public class LoginController : Controller
- {
- //
- // GET: /Login/
- IUserBiz userBiz;
- public LoginController(IUserBiz userBiz)
- {
- this.userBiz = userBiz;
- }
- public JsonResult GetUser(string id)
- {
- Users user = userBiz.GetUser(id);
- return Json(user, JsonRequestBehavior.AllowGet);
- }
- }
- }
这个时候,程序要调用UserBiz,UserBiz要调用UserService,UserService要调用UserRepository,而UserRepository又继承BaseRepository<T>,在每一层调用都有IOC存在。IOC怎么工作呢,先看看Global.asax.cs。
- protected void Application_Start()
- {
- AreaRegistration.RegisterallAreas();
- IoCHelper.InitializeWith(new DependencyResolverFactory());
- ControllerBuilder.Current.SetControllerFactory(new ResolverControllerFactory().GetControllerFactory());
- RegisterRoutes(RouteTable.Routes);
- }
Controller的创建已经交由DependencyResolverFactory这个依赖注入工厂接手,所以我们看到Controller中的IUserBiz而不是UserBiz。那么这个注入在哪里配置着呢?在Host项目下,如下图所示
就是这个Unity.Login.Config。因为目前我只做了个登陆功能,所以在这里只有一个Config文件。那么Unity是怎么读取这个配置文件的呢?我们看看Server端IOC项目下有个UnityContainerBuilder类,他是负责创建依赖注入容器的。在它里面有这么一段代码
- private IEnumerable<string> GetConfigFilePaths()
- {
- string path = AppSettingsHelper.GetString("UnityConfigPath", "Config/Unity");// 默认值为"Config/Unity"
- return Directory.GetFiles(PathHelper.LocateServerPath(path))
- .Where(fullName => Path.GetExtension(fullName).Equals(".config", StringComparison.CurrentCultureIgnoreCase));
- }
就是这个方法来抓取所有的注入配置文件。我们来看看注入配置文件。
- <?xml version="1.0"?>
- <configuration>
- <configSections>
- <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Microsoft.Practices.Unity.Configuration"/>
- </configSections>
- <unity>
- <typeAliases>
- <typeAlias alias="IUserRepository" type="Server.Repository.Interface.IUserRepository, Repository" />
- <typeAlias alias="UserRepository" type="Server.Repository.Implement.UserRepository, Repository" />
- <typeAlias alias="IUserService" type="Server.Application.Interface.IUserService,Application" />
- <typeAlias alias="UserService" type="Server.Application.Implement.UserService, Application" />
- <typeAlias alias="IUserBiz" type="Server.Business.Interface.IUserBiz,Business" />
- <typeAlias alias="UserBiz" type="Server.Business.Implement.UserBiz, Business" />
- <typeAlias alias="IDatabaseFactory" type="Server.Domain.IDatabaseFactory, Domain" />
- <typeAlias alias="DatabaseFactory" type="Server.Domain.DatabaseFactory,Domain" />
- <!--控制器 开始-->
- <typeAlias alias="IControllerFactory" type="System.Web.Mvc.IControllerFactory, System.Web.Mvc,Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
- <typeAlias alias="UnityControllerFactory" type="Server.IOC.IocResolver.UnityControllerFactory,IOC" />
- <typeAlias alias="LoginController" type="MISInfoManage.Web.Controllers.LoginController, MISInfoManage.Web.Host" />
- <!--控制器 结束-->
- </typeAliases>
- <containers>
- <container name="ContainerEF">
- <!--登录-->
- <register type="IDatabaseFactory" mapTo="DatabaseFactory">
- <constructor>
- <param name="connectionName">
- <value value="MISInfoEntities"></value>
- </param>
- </constructor>
- </register>
- <register type="IUserRepository" mapTo="UserRepository">
- <constructor>
- <param name="dataBaseFactory">
- <dependency type="DatabaseFactory"></dependency>
- </param>
- </constructor>
- </register>
- <register type="IUserService" mapTo="UserService">
- <constructor>
- <param name="dataContext">
- <dependency type="DatabaseFactory"></dependency>
- </param>
- <param name="userRepository">
- <dependency type="UserRepository"></dependency>
- </param>
- </constructor>
- </register>
- <register type="IUserBiz" mapTo="UserBiz">
- <constructor>
- <param name="userService">
- <dependency type="UserService"></dependency>
- </param>
- </constructor>
- </register>
- <register type="IControllerFactory" mapTo="UnityControllerFactory">
- </register>
- <register type="LoginController" mapTo="LoginController">
- <constructor>
- <param name="userBiz">
- <dependency type="UserBiz"></dependency>
- </param>
- </constructor>
- </register>
- </container>
- </containers>
- </unity>
- </configuration>
<typeAlias alias="IUserService" type="Server.Application.Interface.IUserService,Application" />
这个配置是一个声明别名的配置,type制定其所在的完整命名空间,所在程序集。类似于这样的配置都一样。我们重点看ContanerEF中的配置。首先是IDatabaseFactory的配置。DataBaseFactory的代码如下
- public class DatabaseFactory : Idisposable, IDatabaseFactory
- {
- DbContext dbContext;
- string connectionName;
- public DatabaseFactory(string connectionName)
- {
- this.connectionName = connectionName;
- }
- public DbContext Get()
- {
- dbContext = new DbContext(connectionName);
- return dbContext;
- }
- public void dispose()
- {
- if (dbContext != null)
- {
- dbContext.dispose();
- }
- }
- }
在UserRepository中我们需要给BaseRepository传递一个databaseFactory,用来创建对应的DBContext。如下所示
- public class UserRepository : BaseRepository<Users>, IUserRepository
- {
- public UserRepository(IDatabaseFactory dataBaseFactory)
- : base(dataBaseFactory)
- { }
- }
在这里,因为我们Login界面所用到的DbContext的链接字符串如下
- <connectionStrings>
- <add name="applicationservices"
- connectionString="data source=.\sqlEXPRESS;Integrated Security=sspI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true"
- providerName="System.Data.sqlClient" />
- <add name="MISInfoEntities" connectionString="Metadata=res://*/edmx.MISInfo.csdl|res://*/edmx.MISInfo.ssdl|res://*/edmx.MISInfo.msl;provider=System.Data.sqlClient;provider connection string="data source=ZZCYIC6VXOK5UXO\MSsqlSERVER08;initial catalog=MISInfo;integrated security=True;multipleactiveresultsets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
- </connectionStrings>
所以注入的时候,我们把DatabaseFactory构造函数中的connectionName注入为MISInfoEntities。对于其他的注入参数,都是采用构造函数注入。相信大家看看就清楚了。在最后我们看看BaseRepository的构造函数。
- public BaseRepository(IDatabaseFactory dataBaseFactory)
- {
- context = dataBaseFactory.Get() as DbContext;
- context.Configuration.LazyLoadingEnabled = true;
- }
由此我们可以看出,如果你的Databasefactory的connectionstring是MISInfoEntities的话,那么BaseRepository接收到的将会是MISInfoEntities(继承DbContext)。如果是PersonEntities,那么Databasefactory的Get方法获取的是PersonEntities(继承DbContext)。这样就可以根据配置文件很容易的更换数据源,或者有时候叫工作单元,从而实现低耦合和控制反转。好了,最后我们一起看看我设计的主界面。
ok,最后我们看看设计代码。
- <UserControl
- x:Class="MISInfoManage.MainPage"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
- xmlns:uriMapper="clr-namespace:System.Windows.Navigation;assembly=System.Windows.Controls.Navigation"
- xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- mc:Ignorable="d"
- xmlns:source="clr-namespace:MISInfoManage.Resources">
- <UserControl.Resources>
- <source:MainPageResource x:Key="Resource"></source:MainPageResource>
- </UserControl.Resources>
- <Grid x:Name="LayoutRoot" Style="{StaticResource LayoutRootGridStyle}" >
- <Grid.Background>
- <ImageBrush ImageSource="/MISInfoManage;component/Images/windows.jpg" Stretch="UniformToFill"></ImageBrush>
- </Grid.Background>
- <Grid.RowDeFinitions>
- <RowDeFinition Height="*"></RowDeFinition>
- <RowDeFinition Height="Auto"></RowDeFinition>
- </Grid.RowDeFinitions>
- <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" Grid.Row="0">
- <StackPanel Orientation="Vertical" HorizontalAlignment="Left">
- <Border CornerRadius="5" BorderBrush="Aqua" BorderThickness="0" MouseMove="Border_MouseMove" MouseLeave="Border_MouseLeave">
- <StackPanel Orientation="Vertical" x:Name="StackPanel1" Margin="10,10,10">
- <Image Source="/MISInfoManage;component/Images/Navigation/UserManage.png" Width="60"/>
- <TextBlock x:Name="Tb_UserManage" Text="{Binding Tb_UserManage,Source={StaticResource Resource}}" Style="{StaticResource MainPageTextStyle}"/>
- </StackPanel>
- </Border>
- <Border CornerRadius="5" BorderBrush="Aqua" BorderThickness="0" MouseMove="Border_MouseMove" MouseLeave="Border_MouseLeave">
- <StackPanel Orientation="Vertical" Margin="10,10">
- <Image Source="/MISInfoManage;component/Images/Navigation/ArchiveInfo.png" Width="60"/>
- <TextBlock x:Name="Tb_ArchiveManage" Text="{Binding Tb_ArchiveManage,0">
- <Image Source="/MISInfoManage;component/Images/Navigation/SystemManage.png" Width="60"/>
- <TextBlock x:Name="Tb_SystemManage" Text="{Binding Tb_SystemManage,Source={StaticResource Resource}}" Style="{StaticResource MainPageTextStyle}"/>
- </StackPanel>
- </Border>
- </StackPanel>
- </ScrollViewer>
- <Button x:Name="BtnLoginInfo" BorderBrush="AliceBlue" Grid.Row="1" Height="30" BorderThickness="1" Background="AliceBlue" FontSize="16"></Button>
- </Grid>
- </UserControl>
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Net;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Documents;
- using System.Windows.Input;
- using System.Windows.Media;
- using System.Windows.Media.Animation;
- using System.Windows.Navigation;
- using System.Windows.Shapes;
- using MISInfoManage.Resources;
- namespace MISInfoManage
- {
- public partial class MainPage : UserControl
- {
- public MainPage()
- {
- InitializeComponent();
- }
- public MainPage(string userName):this()
- {
- this.BtnLoginInfo.Content = string.Format(MainPageResource.Btn_LoginInfo,userName);
- }
- private void Border_MouseMove(object sender, MouseEventArgs e)
- {
- Border border = sender as Border;
- border.Background = new SolidColorBrush(Colors.White);
- border.Background.Opacity = 0.5;
- border.BorderThickness = new Thickness(1);
- }
- private void Border_MouseLeave(object sender, MouseEventArgs e)
- {
- Border border = sender as Border;
- border.Background = new SolidColorBrush();
- border.BorderThickness = new Thickness(0);
- }
- }
- }
好了,本节到此结束,下一节重点进入增删改查,数据验证,双向,单向绑定。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。