nopcommerce中文网

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

导航 - 搜索

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类,大同小异!

nopcommerce未来版本规划

根据nopcommerce官方的说法,下一个版本是nopCommerce3.80,最大的亮点是后台layout的重构,运用了bootstrap框架,还有一些功能的增强以及大量bug的修复,预计发布时间为7-8月份。

ASP.NET Core已经发布,但是不会被用于3.8中,这是相当新的技术,应该给它一些时间来成熟。但最有可能在下一个版本(4.0)中使用它(跳过3.90版本直接进入asp.net core时代)。

鱼头鱼尾视频教程 - 微信扫码登录插件视频教程三


相关说明:
-->基于OAuth2.0的授权模式讲解
-->实现AspNet文件夹里面需要用到的类DictionaryExtensions.cs、JsonHelper.cs、MessagingUtilities.cs、WeiXinGraphData.cs、WeiXinOpenIdData.cs及抽象类OpenAuthenticationClient.cs的代码
-->实现Core文件夹里面需要用到的类Provider.cs、OAuthAuthenticationParameters.cs的代码及创建接口IOAuthProviderWeiXinAuthorizer.cs及实现接口的类WeiXinProviderAuthorizer.cs(此类代码暂不实现)
-->实现依赖注入类DependencyRegistrar.cs的代码

该视频由鱼头鱼尾(QQ:875755898)制作
视频下载地址:http://pan.baidu.com/s/1boZmJO7
插件下载地址:Nop.Plugin.ExternalAuth.WeiXin.zip (69.8KB)

asp.net mvc自定义JsonResult类来防止MaxJsonLength超过限制

前不久在做一个项目的时候,我用到了mvc的webapi返回了一个大数据,结果报了500错误,如下图所示:

Server Error in ‘/’ Application.

Error during serialization or deserialization using the JSON JavaScriptSerializer. The length of the string exceeds the value set on the maxJsonLength property.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.InvalidOperationException: Error during serialization or deserialization using the JSON JavaScriptSerializer. The length of the string exceeds the value set on the maxJsonLength property.

Source Error: 


An unhandled exception was generated during the execution of the current web request.
Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:

Version Information: Microsoft .NET Framework Version:2.0.50727.4952; ASP.NET Version:2.0.50727.4955


从上面可以看出错误的原因是对象在JavaScriptSerializer序列化的时候超过了默认的最大限制,所以我们需要一个类来重写JsonResult从而允许更大的数据。

using System;
using System.Web.Script.Serialization;
 
namespace System.Web.Mvc
{
    public class LargeJsonResult : JsonResult
    {
        const string JsonRequest_GetNotAllowed = "This request has been blocked because sensitive information could be disclosed
to third party web sites when this is used in a GET request. To allow GET requests, set JsonRequestBehavior to AllowGet."
;
        public LargeJsonResult()
        {
            MaxJsonLength = 1024000;
            RecursionLimit = 100;
        }
 
        public int MaxJsonLength { get; set; }
        public int RecursionLimit { get; set; }
 
        public override void ExecuteResult( ControllerContext context )
        {
            if( context == null )
            {
                throw new ArgumentNullException( "context" );
            }
            if( JsonRequestBehavior == JsonRequestBehavior.DenyGet &&
                String.Equals( context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase ) )
            {
                throw new InvalidOperationException( JsonRequest_GetNotAllowed );
            }
 
            HttpResponseBase response = context.HttpContext.Response;
 
            if( !String.IsNullOrEmpty( ContentType ) )
            {
                response.ContentType = ContentType;
            }
            else
            {
                response.ContentType = "application/json";
            }
            if( ContentEncoding != null )
            {
                response.ContentEncoding = ContentEncoding;
            }
            if( Data != null )
            {
                JavaScriptSerializer serializer = new JavaScriptSerializer() { MaxJsonLength = MaxJsonLength, RecursionLimit = RecursionLimit };
                response.Write( serializer.Serialize( Data ) );
            }
        }
    }
}

你可以在Action里面使用
return new LargeJsonResult(){ Data = data }  来替代 return Json(data).
当然你也可以自己控制JavaScriptSerializer的MaxJsonLength:

return new LargeJsonResult() { Data = output, MaxJsonLength = int.MaxValue };

转载自:https://brianreiter.org/2011/01/03/custom-jsonresult-class-for-asp-net-mvc-to-avoid-maxjsonlength-exceeded-exception/