nopcommerce中文网

nopcommerce是国外asp.net领域一个高质量的b2c开源项目,基于EntityFramework和MVC开发,交流QQ群:75272942(2000人超级群)

导航 - 搜索

nopcommerce3.9发布了

喜讯:nopcommerce3.9正式版发布了,点击下载

突出特色
符合PCI DSS 3.2要求。密码登录失败锁定支持(可配置),不允许客户提交以前使用过的密码(可配置),密码至少每90天更改一次(可配置)。
消息模板中支持条件。例如如果不需要航运,你可以隐藏在电子邮件中的航运地址。
折扣要求支持布尔(“and”或“or”或group)。
积分的延迟使用。店主可以指定一段时间后,积分变成可用。
允许客户申请多折扣优惠券代码。
允许商店所有者配置自定义订单号。例如,添加一些前缀或日期。
允许商店所有者管理访问每个客户角色的插件(ACL)。
允许商店所有者指定产品可用范围(将显示而不是一般的“缺货”信息)。
捆绑产品(与其他产品相关的属性)。客户可以输入捆绑项目的数量。
层价格现在支持开始和结束日期(因此删除“特殊价格”产品属性)。
跟踪库存产品变化。
允许商店所有者和供应商回复产品评论。

改进
后台进行重新设计。更人性化的按钮,没有了前面的链接。重新设计的表格。货币、重量、尺寸等的输入。
安装页面重新设计。
货币舍入规则。
添加设置是否显示“默认”的项目,是否显示在顶部菜单(网页,论坛,联系我们等)
现在我们使用模型工厂,它使开发人员定制开发更容易。
现在客户可以在提交退货请求时附加文件(扫描,附加文件等)。默认禁用。
多个XML sitemap文件的支持(如果有50000个以上的记录)。
允许商店所有者指定供应商的地址。
每个商店的新闻和博客评论可以显示每个商店。
添加新闻和博客评论的审批机制。
性能优化。增加了用户代理的加载速度,减少了内存占用。现在网站需要更少的内存。
性能优化。请求之间的缓存折扣信息。在此之前,我们为每个HTTP请求加载所有折扣。
性能优化。当某些事件被触发时,我们只从缓存中移除适当的记录,而不是全部。
性能优化。在每个HTTP请求之间缓存博客和新闻评论的数量。
简化管理区添加“基本高级”模式的切换。
性能优化。现在管理区的供应商和制造商都被缓存。
性能优化。添加了加载所有类别的存储过程。默认禁用。
在管理区域中添加了必填项的提示。
退款申请可以根据自定义号码,日期,状态进行搜索。
博客和新闻评论可以根据日期,文本,批准的状态进行搜索。
付款失败通知客户。
添加描述到每个消息模板。
移动“联系我们”电子邮件到消息模板。现在,店主可以选择一个默认的电子邮件帐户,用于发送这些电子邮件和配置BCC。
贝宝支付插件。显示所有购买项目的列表(可配置)。
"Fixed Rate Shipping" 和"Shipping by weight" 插件合并成一个。
 "Nop.Plugin.Tax.CountryStateZip" 和"Nop.Plugin.Tax.FixedRate" 插件合并成一个。
"Froogle" 插件更名为"Google Shopping"”。
如果“注册方法”设置为“电子邮件验证”,客户应该在编辑后重新验证新的电子邮件。
仅支持的标记将显示在消息模板详细信息页上。
增加了一个设置,指示订单状态应被标记为“完成”(当刚刚发货或交付)。
在管理区如果没有搜索条件,隐藏“搜索”按钮。
为退款申请添加新的消息模板。
供应商可以导入产品(Excel)。
供应商可以导出订单(Excel)。
等等

教你一招 - nopcommerce如何启用redis缓存?

从nopcommerce3.7开始就支持redis缓存了,但是默认没有启用,启用步骤如下:
1、首先安装redis服务器(如果没有的话),参考网址 http://www.redis.net.cn/tutorial/3503.html
2、然后修改web.config如下:
<RedisCaching Enabled="true" ConnectionString="localhost:6379,allowAdmin=true" />
注意要启用allowAdmin=true,否则后台清理缓存的时候会报错。
3、刷新页面就可以了,在Redis Desktop Manager里面看下缓存数据吧。


分享是一种美。版权所有,转载请注明出处 http://www.nopchina.net/

Autofac怎么依赖注入静态方法

Autofac一般是通过Contrller的构造函数或者属性来注入,但是这有一个共同点就是调用这个类的方法一般都是实例方法,也就是要实例化这个类才能调用它的方法。但是如果它是一个静态方法我们又该怎么办呢?其实也很简单,下面我们就通过一个写日志的组件来介绍怎么实现ASP.NET MVC5类的静态方法的依赖注入。因为考虑到很多地方都要用到写日志这个方法,而且我们又不想每次调用都需要new一个对象,所以把调用方法封装成一些静态方法。

DependencyRegistrar.cs

  1. using Autofac;
  2. using Autofac.Integration.Mvc;
  3. using Lanhu.Services;
  4. using Lanhu.Services.MetionNowOrder;
  5. using Lanhu.Services.Member;
  6. using System.Web.Mvc;
  7. namespace Lanhu.Admin
  8. {
  9. public class DependencyRegistrar
  10. {
  11. public static void RegisterDependencies()
  12. {
  13. var builder = new ContainerBuilder();
  14. builder.RegisterControllers(typeof(MvcApplication).Assembly);
  15. builder.RegisterType<Log_UserLogonService>().As<ILog_UserLogon>().InstancePerLifetimeScope();
  16. builder.RegisterType<Log_UserOperateService>().As<ILog_UserOperate>().InstancePerLifetimeScope();
  17. //autofac 注册依赖
  18. IContainer container = builder.Build();
  19. DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
  20.     }
  21.  }
  22. }

在App_Start事件中调用上面的会依赖注入代码:

  1. using Lanhu.Core;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.linq;
  5. using System.Web;
  6. using System.Web.Mvc;
  7. using System.Web.Optimization;
  8. using System.Web.Routing;
  9. namespace Lanhu.Admin
  10. {
  11. public class MvcApplication : System.Web.HttpApplication
  12. {
  13. protected void Application_Start()
  14. {
  15. AreaRegistration.RegisterAllAreas();
  16. FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
  17. RouteConfig.RegisterRoutes(RouteTable.Routes);
  18. BundleConfig.RegisterBundles(BundleTable.Bundles);
  19. DependencyRegistrar.RegisterDependencies();
  20. }
  21. }
  22. }

LogFacade.cs:

  1. using Lanhu.Model;
  2. using Lanhu.Services;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. using System.Web;
  9. using System.Web.Mvc;
  10. namespace Lanhu.Admin.Infrastructure
  11. {
  12. public class LogFacade
  13. {
  14. public static bool AddLogonLog(MLog_UserLogon model)
  15. {
  16. var service = DependencyResolver.Current.GetService<ILog_UserLogon>();
  17. return service.Insert(model);
  18. }
  19. public static bool AddOperateLog(string info,bool isError=false)
  20. {
  21. var service = DependencyResolver.Current.GetService<ILog_UserOperate>();
  22. if (isError)
  23. model.ErrorMsg = info;
  24. else
  25. model.Msg = info;
  26. return service.Insert(model);
  27. }
  28. public static bool AddOperateLog(MLog_UserOperate model)
  29. {
  30. var service = DependencyResolver.Current.GetService<ILog_UserOperate>();
  31. return service.Insert(model);
  32. }
  33. }
  34. }

上面封装了三个静态方法,在方法里面通过DependencyResolver.Current.GetService从Ioc容器中获取相应类型的依赖对象。这个LogFacade使用外观模式,让调用显得很简单。

后台提示消息通知插件 For Nopcommerce V3.8

后台提示消息通知插件,替换nop原生的提示消息通知插件。

效果图

下载:48425_117972_AdminNotificationPlugin.zip (539.4KB)

源代码放在\Plugins目录下,用vs打开重新生成。

转载:http://www.nopcommerce.com/p/2386/admin-notification-plugin-.aspx

nopcommerce3.8发布了

喜讯:nopcommerce3.8正式版发布了,点击下载

该版本的主要变化是增加了店铺管理员的功能,可以更方便的管理店铺以缓解超级管理员的压力,以及重新设计的管理后台等。

突出功能和变化
重新设计了管理后台(响应式)。在产品详细信息页面提供了“基本”和“高级”两种设置(店铺管理者可以选择他想看到/编辑的产品属性)。这种方式让nopcommerce的店铺管理者用起来容易很多。
同时使用多个折扣(累计折扣)。
“颜色”规格属性类型(允许在分类页面上过滤)。
增加了新的产品属性图像块,它非常类似于属性类型“颜色块”。但允许店铺管理员上传图片,而不是选择颜色。属性值对应的图像能更清楚地告诉客户他们所选择的产品。
更好的支持“店内取货”。允许一个店铺管理员配置取货的地点。
在结账页面的“配送到同一个地址”步骤复选框(可配置默认禁用)。
让店铺的管理者自己配置RMA(退货#请求数量)。

改进
产品导出导入支持属性。
根据规范属性的搜索支持“OR”。
分类页面允许店铺管理员自定义“排序”选项。
每个店铺的产品评论(可配置)。
允许在管理后台上传网站Logo。
允许一个店铺管理员创建数据库备份。
验证码支持新版本reCAPTCHA / V2。
现在客户可以在我的帐户页面上看到我的所有产品评论。
现在一个店铺的管理员可以在前台产品、类别、制造商、供应商、主题、博客文章、新闻等页面看到“管理该页面”的链接,
允许店铺管理员对产品评论进行过滤。
论坛允许用户针对每个帖子进行投票。
重新设计了订单详细页面。
高级搜索允许根据供应商进行搜索。
产品批量编辑页面允许编辑产品名称。
当一个店铺管理员在产品详细页面并点击“保存”按钮时,如果产品数量发送变化则显示警告。
缓存相关性能优化。
产品导入的性能优化。
产品导入的时候店铺管理员可以跳过大部分的产品属性(因为他们不是必需的)。
让店铺管理员指定产品是否可以退货。
支持插件描述。
性能.为我的积分页面增加分页支持。
在活动日志中显示“IP地址”。
导入导出类别和制造商。
让店铺管理员指定“在店铺自取”选项是否可用。
让店铺管理员设置发布/未发布主题。
让店铺管理员搜索/过滤的多重身份的订单(订单、发货、付款)。
允许店铺所有者指定发送时间到活动。
申请供应商帐户。允许申请者添加描述和上传Logo
允许供应商管理其信息(我的帐户页面)。
允许一个店铺管理员通过IP地址搜索/过滤客户。
允许店铺所有者指定每个供应商的最大产品数量。
在注册过程中强制输入两次电子邮件(可配置)。
允许用户编辑收藏夹(类似于购物车中的商品)。
私人信息不应该发送给自己。
贝宝支持部分退款。
运费估算使用AJAX(避免页面刷新)。
增加了更多的demo数据。
允许根据客户角色选择活动的收件人。
管理区。允许店铺所有者通过店铺来过滤类别和制造商列表。
“新订单通知”消息模板。增加支持"%Order.OrderNoteAttachmentUrl%",用来显示一个下载附件的链接。
更新Australia post API到最新版本。
升级Canada Post使用web service。
当输入HTML代码的时候管理后台不应该抛出异常。
添加日志当主题更改时候。
添加日志当“删除订单”和“编辑订单”的时候。
删除"Authorize.NET", "Verizon SMS Provider", "Facebook shop"这几个插件。从3.80版本以后,他们将作为第三方扩展插件。
在创建一个新的客户时,客户角色“注册”被默认选中。
把多语言移动语言详细页。
管理后台避免输入重复的页面大小。
设置帐户是否可下载产品。
添加社交网络页面的消息标记。
在订单列表页面删除“根据GUID搜索”。
样本数据。指定每个样品不同的SKU。
谷歌分析插件。允许店铺管理员选择部件区域。
论坛自适应。
管理区。确保有效的电子邮件地址,如果注册的角色被选中。
确保只有超级管理员可以删除其他管理员。确保只有超级管理员可以更改其他管理员的密码。
“卸载插件”按钮的颜色应该是红色的。“安装插件“是绿色的。
性能优化。在一条SQL语句里面删除大量数据。
Redis缓存显着的性能优化。
管理区。重定义了一些按钮。
在管理后台中动态隐藏产品属性(添加产品到订单,添加属性组合)。
添加一个默认的“标准”值在“电子邮件帐户”下拉在非定位标签的邮件模板详细信息”页。
在站点地图和论坛页面添加新的区域。
用户奖励积分更名为“添加积分”,以“添加(减少)积分”的方式更清楚。
不要用“全文”搜索SKU(启用时)。我们应该使用“精确匹配”。重要:如果你已经有了全文启用,然后去行政区>一般杂项设置,禁用全文并使它。这种方式将创建一个新的索引。
允许店铺管理员添加自定义标签。
开发者。更新第三方库到最新版本。
修正所有编译警告。
很多源代码重构以及bug修复。

常见问题之 - 发布到服务器后提示找不到新添加的Controller

我在做nop二次开发的过程中发现了这样一个问题:新增一个公司模块,控制器名为CompanyController,完成所有功能后发布到服务器,一切正常,但是过了一段时间(可能是应用程序池回收)后发现新加的Controller找不到了,好像dll被还原成老版本了,纠结了一段时间后,通过在官方论坛终于找到了原因:
因为有些插件里面需要引用nop.service.dll或者nop.web.dll,并且对应的属性设置成了复制到本地(这样就有可能是一个老的dll),在应用程序池回收或者重启后会iis需要重新加载所有的dll,这时候插件里面老的dll就有可能替换bin目录里面新的dll,从而导致找不到新增的Controller。

友情提醒:凡是插件里面需要引用的nop相关的dll时候一定要在属性里面把复制本地改成false。

相关链接:
http://www.nopcommerce.com/boards/t/25552/newly-added-property-not-found.aspx
http://www.nopcommerce.com/boards/t/40464/add-picture-field-in-blog.aspx

RESTFUL SERVICE 插件 For Nopcommerce V3.7

一款resetful service插件,里面加入了简单的token认证,token通过后台配置页面进行配置,调用api方法的时候需要传递此token来和后台的进行验证,下载后通过后台插件管理安装、配置即可使用。

下载:61187_155782_Nop.Plugin.Misc.RestService.zip (59.1KB)

源代码放在\Plugins目录下,用vs打开重新生成。

WebApi系列~通过HttpClient来调用Web Api接口

HttpClient是一个被封装好的类,主要用于Http的通讯,它在.net,java,oc中都有被实现,当然,我只会.net,所以,只讲.net中的HttpClient去调用Web Api的方法,基于api项目的特殊性,它需要有一个完全安全的环境,所以,你的api控制器看起来有点特别,只有5个方法,而且都是标准的http方法,我觉得这种设计很不错,很清晰,而且为了实现安全性,它不支持使用传统的表单数据,取而代之的是FromBody参数,它指拿HttpRequestMessage里参数,而不是所有的Request数据,这是基于安全方面的考虑。

一 Api接口参数的标准性

Get方式,可以有多个重载,有多个参数

POST方式,只能有一个参数,并且用[FromBody]约束,如果有多个参数,需要以对象的方式进行传递

Put方式,只能有两个参数,其中一个是通过Request.QueryString方式进行传递的,作为要更新对象的主键,别一个是[FromBody]字段,也是一个字段,如果多个字段需要把它封装成对象

标准接口如图

二 调用方,参数的标准性

在客户端进行接口调用时,我们以网页端为例,看一下网页端进行ajax跨域请求的代码

Get方式

    $.ajax({
            url: "http://localhost:52824/api/register",
            type: "GET",
            success: function (data) {
                console.log("json:" + data);
            }
        });

Post方式

     $.ajax({
            url: "http://localhost:52824/api/register",
            type: "POST",
            data: { '': '1' },//这里键名称必须为空,多个参数请传对象,api端参数名必须为value
            success: function (data) {
                console.log("post:" + data);
            }
        });

三 在控制台中实现Get方式获取接口数据(只有异步实现)

      /// <summary>
        /// HttpClient实现Get请求
        /// </summary>
        static async void dooGet()
        {
            string url = "http://localhost:52824/api/register?id=1&leval=5";
            //创建HttpClient(注意传入HttpClientHandler)
            var handler = new HttpClientHandler() { AutomaticDecompression = DecompressionMethods.GZip };

            using (var http = new HttpClient(handler))
            {
                //await异步等待回应
                var response = await http.GetAsync(url);
                //确保HTTP成功状态值
                response.EnsureSuccessStatusCode();

                //await异步读取最后的JSON(注意此时gzip已经被自动解压缩了,因为上面的AutomaticDecompression = DecompressionMethods.GZip)
                Console.WriteLine(await response.Content.ReadAsStringAsync());
            }
        }

四 在控制台中实现Post方式提交数据(只有异步实现)

     /// <summary>
        /// HttpClient实现Post请求
        /// </summary>
        static async void dooPost()
        {
            string url = "http://localhost:52824/api/register";
            var userId = "1";
            //设置HttpClientHandler的AutomaticDecompression
            var handler = new HttpClientHandler() { AutomaticDecompression = DecompressionMethods.GZip };
            //创建HttpClient(注意传入HttpClientHandler)
            using (var http = new HttpClient(handler))
            {
                //使用FormUrlEncodedContent做HttpContent
                var content = new FormUrlEncodedContent(new Dictionary<string, string>()       
                {
                  {"", userId}//键名必须为空
                 });

                //await异步等待回应

                var response = await http.PostAsync(url, content);
                //确保HTTP成功状态值
                response.EnsureSuccessStatusCode();
                //await异步读取最后的JSON(注意此时gzip已经被自动解压缩了,因为上面的AutomaticDecompression = DecompressionMethods.GZip)
                Console.WriteLine(await response.Content.ReadAsStringAsync());
            }

        }

五 在控制台中实现Put方式提交数据(只有异步实现)

        /// <summary>
        /// HttpClient实现Put请求
        /// </summary>
        static async void dooPut()
        {
            string url = "http://localhost:52824/api/register?userid=" + userId;
            var userId = "1";
            //设置HttpClientHandler的AutomaticDecompression
            var handler = new HttpClientHandler() { AutomaticDecompression = DecompressionMethods.GZip };
            //创建HttpClient(注意传入HttpClientHandler)
            using (var http = new HttpClient(handler))
            {
                //使用FormUrlEncodedContent做HttpContent
                var content = new FormUrlEncodedContent(new Dictionary<string, string>()       
                {
                   {"", "数据"}//键名必须为空
                });

                //await异步等待回应

                var response = await http.PutAsync(url, content);
                //确保HTTP成功状态值
                response.EnsureSuccessStatusCode();
                //await异步读取最后的JSON(注意此时gzip已经被自动解压缩了,因为上面的AutomaticDecompression = DecompressionMethods.GZip)
                Console.WriteLine(await response.Content.ReadAsStringAsync());
            }

        }

OK,到这里,我们的客户端如何去调用web api就讲完了,事实上,手机端,平板端也是相关的方式去调用的,它们也都有自己的HttpClient类,大同小异!