Nancy简单实战之NancyMusicStore(三):完善商品信息与管理
前言
上一篇,我们做了不少准备,并且还把我们NancyFx音乐商城的首页打造好了。这一篇主要是完善我们在首页的商品浏览问题和添加对商品的管理。
下面开始正题:
商品详情
首先是查看单个商品的详情:
先回顾一下我们在Home/Index.cshtml中写的热销商品列表
<ul id="album-list">
@foreach (var album in Model)
{
<li>
<a href="javascript:;">
<img alt="@album.Title" src="@album.AlbumArtUrl" />
<span>@album.Title</span>
</a>
</li>
}
</ul>
我们在上一篇是没有给这个列表项加具体的链接,为了和MVC MusicStore保持一致,我们也用了同样的请求链接
给Home/Index.cshtml列表的a标签加上链接,具体如下:
<li>
<a href="/store/details/@album.AlbumId">
<img alt="@album.Title" src="@album.AlbumArtUrl" />
<span>@album.Title</span>
</a>
</li>
所以我们要访问单个商品的详情,是要通过 http://domain.com/store/details/id 的形式来访问。
下面我们就在StoreModule中,添加这一块相应的内容,在StoreModule的构造函数中添加下面的代码:
Get["details/{id:int}"] = _ =>
{
int id = 0;
if (int.TryParse(_.id, out id))
{
string cmd = "public.get_album_details_by_aid";
var album = DBHelper.QueryFirstOrDefault<AlbumDetailsViewModel>(cmd, new
{
aid = id
}, null, null, CommandType.StoredProcedure);
if (album != null)
{
return View["Details", album];
}
}
return View["Shared/Error"];
};
在路由中details/{id:int},参数id后面加了一个限制,让其只能是整数。
然后通过_.id
来取到这个id的具体值,后面的内容就是根据这个id去拿到第一条数据。
最后就是详情页的页面内容了
@inherits Nancy.ViewEngines.Razor.NancyRazorViewBase<NancyMusicStore.ViewModels.AlbumDetailsViewModel>
@{
ViewBag.Title = "Album - " + Model.Title;
}
<h2>@Model.Title</h2>
<p>
<img alt="@Model.Title" src="@Model.AlbumArtUrl" />
</p>
<div id="album-details">
<p>
<em>Genre:</em>
@Model.GenreName
</p>
<p>
<em>Artist:</em>
@Model.ArtistName
</p>
<p>
<em>Price:</em>
@String.Format("{0:F}", Model.Price)
</p>
<p class="button">
<a href="/ShoppingCart/AddToCart/@Model.AlbumId">Add to cart</a>
</p>
</div>
此时单个商品的详情已经可看到了,效果如下:
商品分类列表
下面要查看的是某个分类的所有商品。
我们在通过ajax填充分类信息时,填充的内容是:
$("#categories").append('<li><a href="javascript:;">' + res[i].name + '</a></li>');
现在把具体的链接地址加上,修改成如下代码:
<li><a href="/store/browse/' + res[i].name + '">' + res[i].name + '</a></li>
可以看到,我们要访问某个分类有那些商品,是要通过 http://domain.com/store/browse/name 的形式来访问。
同样在StoreModule的构造函数添加一个相应的处理:
Get["browse/{genre}"] = _ =>
{
string genre = _.genre;
ViewBag.Genre = genre;
string cmd = "public.get_album_list_by_gname";
var albumList = DBHelper.Query<AlbumListViewModel>(cmd, new
{
gname = genre
}, null, true, null, CommandType.StoredProcedure).ToList();
return View["Browse", albumList];
};
其对应的页面内容是和首页的热销商品一个形式的,只是数量比较多而已。
在这里点击某个商品也是能跳到对应的详情页的,具体如下:
@inherits Nancy.ViewEngines.Razor.NancyRazorViewBase<List<NancyMusicStore.ViewModels.AlbumListViewModel>>
@{
ViewBag.Title = "Browse Albums";
}
<div class="genre">
<h3><em>@ViewBag.Genre</em> Albums</h3>
<ul id="album-list">
@foreach (var album in Model)
{
<li>
<a href="/store/details/@album.AlbumId">
<img alt="@album.Title" src="@album.AlbumArtUrl" />
<span>@album.Title</span>
</a>
</li>
}
</ul>
</div>
示例为Disco分类下面的列表页:
到这里,我们已经完成了商品信息浏览的相关处理。
下面就添加对这些商品的管理,这里的管理实则是对专辑(Albums)信息的CURD操作。
商品管理
这些操作的具体内容就不详细展开了。在Modules文件夹下面新建一个StoreManagerModule.cs
具体内容如下(省略了部分代码,占的篇幅有点多) :
using Nancy;
using Nancy.ModelBinding;
using Nancy.Security;
using NancyMusicStore.Common;
using NancyMusicStore.Models;
using NancyMusicStore.ViewModels;
using System;
using System.Data;
namespace NancyMusicStore.Modules
{
public class StoreManagerModule : NancyModule
{
public StoreManagerModule() : base("/storemanager")
{
Get["/"] = _ =>
{
string cmd = "get_all_albums";
var list = DBHelper.Query<AlbumListViewModel>(cmd, null, null, true, null, CommandType.StoredProcedure);
return View["Index", list];
};
Get["/create"] = _ =>{};
Post["/create"] = _ =>{};
Get["/details/{id:int}"] = _ =>{};
Get["/edit/{id:int}"] = _ =>{};
Post["/edit"] = _ =>{};
Get["/delete/{id:int}"] = _ =>{};
Post["/delete/{id:int}"] = _ =>{};
Get["/getallgenres"] = _ =>{};
Get["/getallartists"] = _ =>{};
}
}
}
视图代码就不放出来了,可以在最后的文章中去下载。
商品管理的效果如下:
我们在_Layout.cshtml中指定了商品管理的入口在导航菜单的【Admin】中
但是现在这种情况下,是任何人都可以对商品信息修改,这显然是不合理的。
在MVC MusicStore中是通过Membership来处理这个问题的。对于这一块我是通过Nancy本身的Forms认证来处理。
Forms认证,有几个重要的地方需要说明一下:
在启动器中要添加Forms认证的支持
实现一个继承IUserMapper接口的UserMapper类
通过IoC去注册这个UserMapper类
在要认证的地方添加this.RequiresAuthentication()即可
我们先在web.config的appSettings中添加一个配置项,用来指定没授权用户的登录url
<add key="logonUrl" value="~/account/logon" />
在启动器(CustomerBootstrapper.cs)中,是这样进行处理的
protected override void RequestStartup(TinyIoCContainer container, IPipelines pipelines, NancyContext context)
{
base.RequestStartup(container, pipelines, context);
//form authentication
var formsAuthConfiguration = new FormsAuthenticationConfiguration
{
RedirectUrl = ConfigHelper.GetAppSettingByKey("logonUrl"),
UserMapper = container.Resolve<IUserMapper>(),
};
FormsAuthentication.Enable(pipelines, formsAuthConfiguration);
}
protected override void ConfigureRequestContainer(TinyIoCContainer container, NancyContext context)
{
base.ConfigureRequestContainer(container, context);
container.Register<IUserMapper, UserMapper>();
}
在这里,用的IoC容器也是Nancy本身就支持的TinyIoc,没有用业界流行的AutoFac。
UserMapper的实现如下 :
internal class UserMapper : IUserMapper
{
public IUserIdentity GetUserFromIdentifier(Guid identifier, NancyContext context)
{
string cmd = "public.get_user_by_userid";
var user = DBHelper.QueryFirstOrDefault<SysUser>(cmd, new
{
uid = identifier.ToString()
}, null, null, CommandType.StoredProcedure);
return user == null
? null
: new UserIdentity
{
UserName = user.SysUserName,
Claims = new[] { "SystemUser" }
};
}
}
到这一步,Forms的配置已经OK了。
有关Nancy中Forms认证的内容,可以参考之前的博客 Nancy之Forms authentication的简单使用
下面就只要在StoreManagerModule的构造函数中添加 this.RequiresAuthentication();
这时,我们想直接通过入口来打开管理界面,就会跳转到登录界面,要求我们先进行登录才可以。
效果图如下:
可以看到,我们的效果已经达到了。
下面仔细观察一下url,发现参数中还附带了returnUrl,可以让我们登录后跳转到指定的页面。
登录注册相关的操作放在在AccountModule中
下面来看看这个returnUrl的处理
Get["/logon"] = _ =>
{
var returnUrl = this.Request.Query["returnUrl"];
ViewBag.returnUrl = returnUrl;
return View["LogOn"];
};
Post["/logon"] = _ =>
{
var logonModel = this.Bind<LogOnModel>();
string cmd = "public.get_user_by_name_and_password";
var user = DBHelper.QueryFirstOrDefault<SysUser>(cmd, new
{
uname = logonModel.SysUserName,
upwd = logonModel.SysUserPassword
}, null, null, CommandType.StoredProcedure);
if (user == null)
{
return View["LogOn"];
}
else
{
MigrateShoppingCart(user.SysUserName);
var redirectUrl = string.IsNullOrWhiteSpace(logonModel.ReturnUrl) ? "/" : logonModel.ReturnUrl;
return this.LoginAndRedirect(Guid.Parse(user.SysUserId), fallbackRedirectUrl: redirectUrl);
}
};
returnUrl是以QueryString的形式存在,所以在打开登录界面的时候,用一个viewbag把它存起来
登录的时候再POST到后台。登录的POST操作用到了Nancy的ModelBinding,与MVC的模型绑定是类似的,可以参考 Nancy之ModelBinding(模型绑定)。
所以在LogOnModel中,添加了一个属性用于绑定这个returnUrl。
public class LogOnModel
{
public string SysUserName { get; set; }
public string SysUserPassword { get; set; }
public string ReturnUrl { get; set; }
}
到这里,商品信息和管理已经完成了。实战的第二篇文章也就结束了。
下面一篇的内容就是要完成购物车的内容。
本文也已经同步到 Nancy之大杂烩
Nancy简单实战之NancyMusicStore(三):完善商品信息与管理的更多相关文章
- Nancy简单实战之NancyMusicStore(六):写在最后
前言 由于公司搬家后,住的地方离上班的地方远了N倍,以前是走路十多分钟就可以到公司的,上班时间也从9:00提早到8:30 现在每天上班都是先坐公交,然后再坐地铁,在这段路上比较浪费时间而且每天都是要6 ...
- Nancy简单实战之NancyMusicStore(二):打造首页
前言 继上一篇搭建好项目之后,我们在这一篇中将把我们NancyMusicStore的首页打造出来. 布局 开始首页之前,我们要先为我们的整个应用添加一个通用的布局页面,WebForm中母版页的概念. ...
- Nancy简单实战之NancyMusicStore(四):实现购物车
前言 上一篇,我们完成了商品的详情和商品的管理,这一篇我们来完成最后的一个购物车功能. 购物车,不外乎这几个功能:添加商品到购物车,删除购物车中的商品,对购物车中的商品进行结算. MVC MusicS ...
- Nancy简单实战之NancyMusicStore(一):准备工作和搭建项目
开发环境 OS : Windows 10 10.0.14393 IDE : Visual Studio 2015 Community With Update 3 Database : PostgreS ...
- Nancy简单实战之NancyMusicStore(五):部署上线
前言 经过本系列前面四篇文章,NancyMusicStore已经开发完成了,下面就差部署上线了,我们会在两个不同的环境部署.其实之前的文章也有讲解在 Linux下部署的相关事宜.下面开始本文的内容. ...
- 简单的抓取淘宝关键字信息、图片的Python爬虫|Python3中级玩家:淘宝天猫商品搜索爬虫自动化工具(第一篇)
Python3中级玩家:淘宝天猫商品搜索爬虫自动化工具(第一篇) 淘宝改字段,Bugfix,查看https://github.com/hunterhug/taobaoscrapy.git 由于Gith ...
- AspNetCore-MVC实战系列(三)之个人中心
AspNetCore - MVC实战系列目录 . 爱留图网站诞生 . git源码:https://github.com/shenniubuxing3/LovePicture.Web . AspNetC ...
- 移动端web开发初探之Vuejs的简单实战
这段时间在做的东西,是北邮人论坛APP的注册页.这个注册页是内嵌的网页,因为打算安卓和IOS平台同时使用.因此实际上就是在做移动端的web开发了. 在这过程中遇到了不少有意思的东西. DEMO的git ...
- SAS数据挖掘实战篇【三】
SAS数据挖掘实战篇[三] 从数据挖掘概念到SAS EM模块和大概的流程介绍完之后,下面的规划是[SAS关联规则案例][SAS聚类][SAS预测]三个案例的具体操作步骤,[SAS的可视化技术]和[SA ...
随机推荐
- Android学习笔记之Intent(2)
打开网页 package com.jiahemeikang.helloandroid; import java.io.File; import com.jiahemikang.service.Echo ...
- PAT (Advanced Level) 1084. Broken Keyboard (20)
简单题. #include<cstdio> #include<cstring> #include<cmath> #include<vector> #in ...
- 公司搬家,拿了个费机器,没root密码,又忘了怎么搞了,
grub中找到ro->rw single init=/bin/bash passwd root
- 更改CI框架默认访问路径及去掉index.php
下面是去掉index.php的操作 PHP CodeIgniter(CI)去掉 index.php - Langjun - 博客园 设置访问的默认路径是在
- 好用的消息对话框-TipsWindown
TipsWindow的官网地址为:http://leotheme.cn/javascript/jquery-plugins-tipswindow-2-0.html 这个是一个爱好者维护的!在这里感谢这 ...
- Unity3D中的函数方法及解释
一.刷新函数 Update 当MonoBehaviour启用时,其Update在每一帧被调用. LateUpdate 当Behaviour启用时,其LateUpdate在每一帧被调用. FixedUp ...
- Mac搭建Hadoop源码阅读环境
1.本次Hadoop源码阅读环境使用的阅读工具是idea,Hadoop版本是2.7.3.需要安装的工具包括idea.jdk.maven.protobuf等 2.jdk,使用的版本是1.8版,在jdk官 ...
- LPC2478中断控制器以及串口详解
LPC2478的中断系统 LPC2478使用的是ARM PrimeCell向量中断控制器,一共支持32个中断向量,处于AHB空间便于系统快速访问,在中断向量的硬件优先级上还有一层可以用户自己设计的软件 ...
- VS2010环境下用ANSI C创建DLL和使用方法(转)
源:VS2010环境下用ANSI C创建DLL和使用方法 . 创建DLL工程 1.2 创建一个dll工程. 操作:a.文件->新建->项目->Win32控制台应用程序. b.输入工程 ...
- uCOS-iii 中定义的一些常量
uCOS-iii 中定义的一些常量 uCOS-iii 中有许多宏定义的量,这些量不需要全部记住是什么意思,因为在阅读代码的时候可以选中变量或宏定义然后右键查看定义,就可以知道它代表的什么意思.但是如果 ...