LightSwitch HTML 图片管理器使用 WCF RIA Services





5.00/5 (4投票s)
这是一个使用 WCF RIA Services 将文件上传和查看到 Web 服务器的 Visual Studio LightSwitch HTML 图片文件管理器。
注意: 在 https://pictureuploader.lightswitchhelpwebsite.com/htmlclient/ 尝试在线演示(请使用您的 LightSwitchHelpWebsite.com 用户名和密码进行访问)。
引言
本文介绍了一个 **Visual Studio LightSwitch HTML 图片文件管理器**,它使用 **WCF RIA Services** 将文件上传和查看到 Web 服务器。使用 **WCF RIA Services** 可以让应用程序通过在显示列表时使用服务器硬盘上存储的缩略图,并在用户选择时显示完整的原始图像,从而提供快速的性能。**WCF RIA Services** 使代码清晰易懂,因为它公开的实体看起来就像普通的表,但实际上是从硬盘保存和读取图片。
本示例始于在 Full Control LightSwitch (ServerApplicationContext and Generic File Handlers and Ajax Calls) 中创建的应用程序。
在此应用程序中,您可以搜索用户和图片名称(有关创建搜索屏幕的教程,请参阅 Server Side Search using the LightSwitch HTML Client)。
用户可以选择 **编辑我的帐户** 来更新他们的个人资料并上传图片。
在 **个人资料页面** 上,只显示用户的照片。用户可以单击照片来编辑其标题。
用户可以选择 **添加用户图片** 来上传照片。
上传照片后,它将显示在预览中。
业务规则允许用户只上传 5 张图片。
项目
LightSwitch 项目是一个普通的 **LightSwitch HTML** 项目,带有一个 **WCF RIA Service**。 **WCF RIA Service** 将图像保存到服务器硬盘并从服务器硬盘读取图像。它公开了两个实体:`UserPictures` 和 `BigPictures`。这两个实体都指向服务器硬盘上的相同文件。之所以有两个实体,是因为在我们要显示原始图像时使用 `BigPictures`。在我们要显示图像缩略图时(这在查看图片列表时提供了更快的性能)使用 `UserPictures`。
显示图片
如果我们查看 **主** 屏幕,我们会看到 `UserPictures` 绑定到 **磁贴列表** 控件,而 `GetBigPicture` 实体则在一个 **弹出窗口** 中(当您单击图片时打开)。
WCF RIA Service 具有这两个实体的定义。
public class UserPicture
{
[Key]
public int Id { get; set; }
public string UserName { get; set; }
public string PictureName { get; set; }
public string ActualFileName { get; set; }
public byte[] FileImage { get; set; }
}
public class BigPicture
{
[Key]
public int Id { get; set; }
public string ActualFileName { get; set; }
public byte[] FileImage { get; set; }
}
为了检索照片,使用了以下代码。请注意,它实际上是从 `Picture` 表(这是一个普通 SQL 表)获取所有数据,然后用硬盘上的文件内容(在本例中是缩略图)替换 `FileImage` 属性。
#region GetPictures
[Query(IsDefault = true)]
public IQueryable<UserPicture> GetPictures()
{
var colUserPictures = new List<UserPicture>();
colUserPictures = (from Pictures in this.Context.Pictures
select new UserPicture
{
Id = Pictures.Id,
UserName = Pictures.UserName,
PictureName = Pictures.PictureName,
ActualFileName = Pictures.ActualFileName,
}).ToList();
// Add the Pictures to the collection
foreach (var Picture in colUserPictures)
{
try
{
// Load Image thumbnail
string strThumbnailFile =
String.Format("{0}_thumb{1}",
Path.GetFileNameWithoutExtension(Picture.ActualFileName),
Path.GetExtension(Picture.ActualFileName));
string strPath = string.Format(@"{0}\{1}",
GetFileDirectory(), strThumbnailFile);
FileStream sourceFile = new FileStream(strPath, FileMode.Open);
long FileSize;
FileSize = sourceFile.Length;
byte[] getContent = new byte[(int)FileSize];
sourceFile.Read(getContent, 0, (int)sourceFile.Length);
sourceFile.Close();
Picture.FileImage = getContent;
}
catch
{
// Do nothing if image not found
}
}
return colUserPictures.AsQueryable();
}
#endregion
检索单个大图片时,使用以下方法。
#region GetBigPicture
public BigPicture GetBigPicture(int? Id)
{
var objPicture = new BigPicture();
if (Id != null)
{
objPicture = (from Pictures in this.Context.Pictures
where Pictures.Id == Id
select new BigPicture
{
Id = Pictures.Id,
ActualFileName = Pictures.ActualFileName,
}).FirstOrDefault();
// Add the Pictures to the collection
if (objPicture != null)
{
try
{
string strPath = string.Format(@"{0}\{1}",
GetFileDirectory(), objPicture.ActualFileName);
FileStream sourceFile = new FileStream(strPath, FileMode.Open);
long FileSize;
FileSize = sourceFile.Length;
byte[] getContent = new byte[(int)FileSize];
sourceFile.Read(getContent, 0, (int)sourceFile.Length);
sourceFile.Close();
objPicture.FileImage = getContent;
}
catch
{
// Do nothing if image not found
}
}
}
return objPicture;
}
#endregion
删除图片
用户可以编辑自己的图片。当他们这样做时,他们可以选择 **删除** 图片(这将同时删除服务器硬盘上的原始图片和图像缩略图)。
在屏幕设计器中,我们可以看到 **删除** 按钮。
**删除** 按钮的 **JavaScript** 代码实际上非常简单,与不调用 **WCF RIA Service** 时使用的代码完全相同。
myapp.EditPicture.Delete_execute = function (screen) {
// Delete the current picture record
screen.UserPicture.deleteEntity();
// Save the changes
return myapp.commitChanges().then(null, function fail(e) {
// There was an error -- cancel changes
myapp.cancelChanges();
// Throw the error so it will display
// to the user
throw e;
});
};
调用了底层的 **WCF RIA Service** 方法。
#region DeleteFile
public void DeleteFile(UserPicture objFileRecord)
{
string strCurrentUserName = GetCurrentUserName();
// This picture must belong to the person deleting it
if (strCurrentUserName == objFileRecord.UserName)
{
// Delete file
try
{
string strFileDirectory = GetFileDirectory();
string strFileName = objFileRecord.ActualFileName;
string strThumbnailFile =
String.Format(@"{0}_thumb{1}",
Path.GetFileNameWithoutExtension(strFileName),
Path.GetExtension(strFileName));
// Delete the thumbnail and the picture
File.Delete(Path.Combine(strFileDirectory, strThumbnailFile));
File.Delete(Path.Combine(strFileDirectory, objFileRecord.ActualFileName));
}
catch
{
// Do nothing if file does not delete
}
// Get database picture record
var objPicture = (from Pictures in this.Context.Pictures
where Pictures.Id == objFileRecord.Id
where Pictures.UserName == strCurrentUserName
select Pictures).FirstOrDefault();
if (objPicture != null)
{
// Delete database picture record
this.Context.Pictures.DeleteObject(objPicture);
this.Context.SaveChanges();
}
}
}
#endregion
上传图片
为了上传图片,我们借用了 LightSwitch HTML Client Tutorial - Contoso Moving 教程中的代码(您可以在 此链接 处找到演练)。该示例与本示例的主要区别在于,在 **Contoso** 示例中,图片存储在数据库中,而不是硬盘上。
**添加图片** 屏幕的布局很简单。它包含 `UserPicture` 实体,其中 `FileImage` 属性绑定到 **自定义控件**。
使用以下代码来渲染 **自定义控件** 的内容。
myapp.AddPicture.FileImage_render = function (element, contentItem) {
// Create the Image Uploader
createImageUploader(element, contentItem, "max-width: 300px; max-height: 300px");
};
调用了底层的 **WCF RIA Service** 方法。
#region InsertFile
public void InsertFile(UserPicture objFileRecord)
{
// Get current user
string strCurrentUserName = GetCurrentUserName();
// The file name will be prepended with the userName
string strActualFileName = String.Format("{0}_{1}.png",
strCurrentUserName, DateTime.Now.Ticks.ToString());
// Create a Picture object
Picture objPicture = this.Context.CreateObject<Picture>();
// Ste values
objPicture.ActualFileName = strActualFileName;
objPicture.PictureName = objFileRecord.PictureName;
// User can only Insert a picture under their identity
objPicture.UserName = strCurrentUserName;
// Get the local directory
string strFileDirectory = GetFileDirectory();
EnsureDirectory(new System.IO.DirectoryInfo(strFileDirectory));
// Set a value for the file path
string filePath = Path.Combine(strFileDirectory, strActualFileName);
// Convert file to stream
using (Stream FileImageStream =
new MemoryStream(objFileRecord.FileImage))
{
FileInfo fi = new FileInfo(filePath);
// If file exists - delete it
if (fi.Exists)
{
try
{
fi.Delete();
}
catch
{
// could not delete
}
}
using (FileStream fs = File.Create(filePath))
{
// Save the file
SaveFile(FileImageStream, fs);
fs.Close();
}
// Make a thumbnail of the file
MakeThumbnail(filePath);
}
// Update LightSwitch Database
this.Context.Pictures.AddObject(objPicture);
this.Context.SaveChanges(
System.Data.Objects.SaveOptions.DetectChangesBeforeSave);
// Set the objFileRecord.Id to the ID that was inserted
// In the Picture table
objFileRecord.Id = objPicture.Id;
// Set Actual File Name
objFileRecord.ActualFileName = strActualFileName;
}
#endregion
Business Rules
为了实现用户只能上传 5 张图片的业务规则,我们打开 `UserPicture` 实体,然后选择 `UserPictures_Inserting` 方法。
我们为该方法使用以下代码。
partial void UserPictures_Inserting(UserPicture entity)
{
string strCurrentUser = this.Application.User.Identity.Name;
// Only allow each user to insert 5 pictures
if (this.DataWorkspace.ApplicationData.Pictures
.Where(x => x.UserName == strCurrentUser).Count() > 4)
{
throw new Exception(string.Format("{0} can only add 5 pictures.", entity.UserName));
}
else
{
// The UserName is set to the person who is logged in
entity.UserName = this.Application.User.Identity.Name;
}
}
一个强大的框架
**WCF RIA Services** 允许我们创建复杂的功能并将其公开为实体。这使我们能够使用相对简单的代码编写 JavaScript 层。
特别感谢
特别感谢 **Stephen Provine** 和 **Matt Evans** 的宝贵协助。
LightSwitch 帮助网站文章
- 一个端到端的 Visual Studio LightSwitch HTML5 应用程序
- 完全控制 LightSwitch(ServerApplicationContext 和通用文件处理程序及 Ajax 调用)
- 在 Visual Studio LightSwitch HTML 客户端中保存数据(包括自动保存)
- 使用 Wijmo Grid 在 LightSwitch HTML Client 中创建桌面体验
- 使用 ServerApplicationContext 创建 ASP.NET Web Forms CRUD 页面
- 在 Visual Studio LightSwitch 中使用 Promises
- 在 LightSwitch HTML 客户端中检索当前用户
- 编写实现 Visual Studio LightSwitch 中绑定模式的 JavaScript
- 在 LightSwitch HTML Client 中实现 Wijmo 径向仪表
- 在 LightSwitch HTML Client Preview 中编写 JavaScript
- 在 Visual Studio LightSwitch 中使用 TypeScript 创建 JavaScript
- 使用 JQuery ThemeRoller 为您的 LightSwitch 网站设置主题
- 在 Visual Studio LightSwitch HTML Client (Preview) 中使用 Toastr)
LightSwitch 团队 HTML 和 JavaScript 文章
- 使用地图控件可视化列表数据
- 使用 jQuery Mobile 增强 LightSwitch 控件
- LightSwitch HTML Client 中的自定义控件和数据绑定 (Joe Binder)
- 使用 LightSwitch HTML Client 创建屏幕 (Joe Binder)
- LightSwitch HTML Client:架构概述 (Stephen Provine)
- 在 LightSwitch 中编写 JavaScript 代码 (Joe Binder)
- LightSwitch HTML Client 的新 API (Stephen Provine)
- 用于 LightSwitch 服务器交互的新 API:ServerApplicationContext
- 构建 LightSwitch HTML Client:eBay 日常交易 (Andy Kung)