Lightswitch Desktopclinet 本质就是一个silverlight 桌面客户端程序,当然也有对应的asp.net后台服务,数据的真正处理都在后台端。那也可以尝试以WEB API 进行自定义的调用。(注:LS是很方便,但太不注意性能,获取的数据都是整个表及关联性数据)。
服务器端处理:
1 GLOBAL文件,添加WEBAPI路由注册信息
public class Global : System.Web.HttpApplication
{
protected void Application_Start(object sender, EventArgs e)
{
// needs references: System.Web.Http, System.web.Http.WebHost en System.Net.Http
RouteTable.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { action = "get", id = RouteParameter.Optional }
);
}
}
2. 添加 一个调用LS环境的基类(如果要使用现成的LS的数据访问功能,如自己用ADO.NET则无需)
或 PM> Install-package the lightswitchtoolbox.webapicommanding.server
手工代码:
LightSwitchApiControllerbase.cs
public abstract class LightSwitchApiControllerbase : ApiController { private ServerApplicationContext _context; public ServerApplicationContext Context { get { return _context; } } public ServerApplicationContext GetContext() { return _context; } public LightSwitchApiControllerbase() { _context = ServerApplicationContext.Current; if (_context == null) { _context = ServerApplicationContext.CreateContext(); } } }
3.实现WEB API
public class CommandController : LightSwitchApiControllerbase { [HttpGet] public IEnumerable<string> TestGetCommand() { List<string> list = new List<string>(); try { using (var ctx = this.Context) { if (ctx.Application.User.HasPermission(Permissions.CanSendCommand)) { list.Add("can CanSendCommand "); } if (ctx.Application.User.HasPermission(Permissions.CanSendCommand)) { list.Add("value 1"); list.Add("value 2"); string lastNameFirstCustomer = ctx.DataWorkspace.ApplicationData.Customers.First().LastName; list.Add(lastNameFirstCustomer); return list; } } } catch (Exception ex) { list.Add(ex.Message); } return list; } [HttpPost] public HttpResponseMessage TestCommand(SimpleCommandRequestParameters parameters) { Thread.Sleep(3000); string s=""; try { using (var ctx = this.Context) { if (ctx.Application.User.HasPermission(Permissions.CanSendCommand)) { string lastNameFirstCustomer = ctx.DataWorkspace.ApplicationData.Customers.First().LastName; s = "ok for " + parameters.ReqParam + " for " + lastNameFirstCustomer; } else { s = "NOT OK for " + parameters.ReqParam; } } } catch(Exception ex) { s = ex.Message; } return Request.CreateResponse<SimpleCommandResponseParameters>(HttpStatusCode.Accepted, new SimpleCommandResponseParameters { RespParam = s }); } }
4. 添加请求响应参数帮助类,上面引用到的,注:同时在客户端也添加此文件连接以共享代码
public class SimpleCommandResponseParameters { public string RespParam { get; set; } }
public class SimpleCommandRequestParameters { public string ReqParam { get; set; } }
客户端处理:
1. 添加上述二个请求响应帮助类,以连接方式共享服务器代码
2.添加一个API代理调用类
using Microsoft.LightSwitch.Client; using Microsoft.LightSwitch.Threading; using Newtonsoft.Json; using System; using System.IO; using System.Net; using System.Reflection; using System.Runtime.InteropServices.Automation; using System.Threading; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Ink; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; namespace LightSwitchApplication { public static class LightSwitchCommandProxy { private static object GetPrivateProperty(Object obj, string name) { BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public; Type type = obj.GetType(); PropertyInfo field = type.GetProperty(name, flags); return field.GetValue(obj, null); } private static object GetPrivateField(Object obj, string name) { BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public; Type type = obj.GetType(); FieldInfo field = type.GetField(name, flags); return field.GetValue(obj); } public static void StartWebApiCommand<T>(this IScreenObject screen, string commandrelativePath, object data, Action<Exception, T> callback) { Uri baseAddress = null; baseAddress = GetBaseAddress(); HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(new Uri(baseAddress, commandrelativePath)); webRequest.Method = "POST"; webRequest.ContentType = "application/json"; if (System.Windows.Application.Current.IsRunningOutOfBrowser) //OOB模式,设置COOKIE { Object userState = null; var auths = Application.Current.AuthenticationService.LoadUser((loadOp) => { }, userState); var op = GetPrivateField(auths, "operation"); var svc = GetPrivateProperty(op, "Service"); System.Net.CookieContainer cc = (System.Net.CookieContainer)GetPrivateProperty(svc, "CookieContainer"); webRequest.CookieContainer = cc; // CookieContainer的获取可以放在Application_LoggedIn 事件里获取,不用每次都取一下 //public partial class Application //{ // partial void Application_LoggedIn() // { // } //} } webRequest.BeginGetRequestStream(iar => { var requestStream = webRequest.EndGetRequestStream(iar); SerializeObject(data, requestStream); webRequest.BeginGetResponse(iar2 => { WebResponse webResponse; try { webResponse = webRequest.EndGetResponse(iar2); } catch (Exception ex) { screen.Details.Dispatcher.BeginInvoke(() => { callback(ex, default(T)); }); return; } var result = Deserialize<T>(new StreamReader(webResponse.GetResponseStream())); screen.Details.Dispatcher.BeginInvoke(() => { callback(null, result); }); }, null); }, null); } //for a get,不带COOKIE,有可能会被拒绝 public static void StartWebApiRequest<T>(this IScreenObject screen, string requestRelativePath, Action<Exception, T> callback) { Uri serviceUri = new Uri(GetBaseAddress(), requestRelativePath); WebRequest.RegisterPrefix("http://", System.Net.Browser.WebRequestCreator.BrowserHttp); WebRequest.RegisterPrefix("https://", System.Net.Browser.WebRequestCreator.BrowserHttp); //out of browser does not work here ! WebRequest webRequest = WebRequest.Create(serviceUri); webRequest.UseDefaultCredentials = true; webRequest.Method = "GET"; webRequest.BeginGetResponse(iar2 => { WebResponse webResponse; try { webResponse = webRequest.EndGetResponse(iar2); } catch (Exception ex) { screen.Details.Dispatcher.BeginInvoke(() => { callback(ex, default(T)); }); return; } var result = Deserialize<T>(new StreamReader(webResponse.GetResponseStream())); screen.Details.Dispatcher.BeginInvoke(() => { callback(null, result); }); }, null); } public static Uri GetBaseAddress() { Uri baseAddress = null; Dispatchers.Main.Invoke(() => { baseAddress = new Uri(new Uri(System.Windows.Application.Current.Host.Source.AbsoluteUri), "../../"); }); return baseAddress; } private static void SerializeObject(object data, Stream stream) { var serializer = new JsonSerializer(); var sw = new StreamWriter(stream); serializer.Serialize(sw, data); sw.Flush(); sw.Close(); } private static T Deserialize<T>(TextReader reader) { var serializer = new JsonSerializer(); return serializer.Deserialize<T>(new JsonTextReader(reader)); } } }
注:添加一下Newtonsoft.Json引用
3.客户端调用,新增一个屏幕,加上按钮事件,如下:
partial void TestPostCommand_Execute()
{
string commandrelativePath = "api/Command/TestCommand";
this.StartWebApiCommand<SimpleCommandResponseParameters>(commandrelativePath,
new SimpleCommandRequestParameters { ReqParam = "hello" },
(error, response) =>
{
IsBusy = false;
if (error != null)
{
this.ShowMessageBox("error = " + error.ToString());
}
else
{
this.ShowMessageBox("result = " + response.RespParam);
}
});
}
partial void TestGetCommand_Execute()
{
string commandrelativePath = "api/Command/TestGetCommand";
this.StartWebApiRequest<List<string>>(commandrelativePath,
(error, response) =>
{
if (error != null)
{
this.ShowMessageBox("error = " + error.ToString());
}
else
{
var result = string.Empty;
response.ForEach(s => result += (s + " "));
this.ShowMessageBox(result);
}
});
}