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);
}
});
}