首页 > 解决方案 > ASP.NET MVC:将模型数据存储为 JSON 字符串

问题描述

我正在开展一个(暂时)自学项目,以创建一个会计软件包来管理客户、发票、估计等数据。

我目前正在开发客户系统。我知道如何设置应用程序以将不同的数据存储在不同的列中,但我想学习如何将所有内容存储为 JSON 字符串。

楷模:

[Table("Customers")]
public partial class CustomerDb
{
    public int Id { get; set; }
    public string Obj_Data { get; set; }
}

然后,我为各个数据创建了一个 Customer 模型:

public partial class Customer
{
    public int Company_Id { get; set; }
    public string Customer_Name { get; set; }
    public string Customer_Company { get; set; }
    public Dictionary<string, string> Phones { get; set; }
    public List<Dictionary<string, string>> Emails { get; set; }
    public string Terms { get; set; }
    public Dictionary<string, string> Locations { get; set; }
    public Dictionary<string, string> Preferences { get; set; }
    public string Exemptions { get; set; }
}

添加新客户视图:

@model BSheets.Models.Custom.CustomerDb

@{
    ViewBag.Title = "Add";
}

@using (Html.BeginForm()) 
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">
        <h4>Customer</h4>
        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })
        <div class="form-group">
            @Html.LabelFor(model => model.Obj_Data, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
                @Html.TextAreaFor(model => model.Obj_Data, htmlAttributes: new { @class = "form-control" })
                @Html.ValidationMessageFor(model => model.Obj_Data, "", new { @class = "text-danger" })
            </div>
        </div>

        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Add" class="btn btn-default" />
            </div>
        </div>
    </div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

客户控制器:

using BSheets.Models;
using BSheets.Models.Custom;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;

namespace BSheets.Controllers
{
    public class CustomerController : Controller
    {
        private BSheetsEntities _db = new BSheetsEntities();
        private ViewModel _vm = new ViewModel();

        // GET: Customer
        public ActionResult Index(string search)
        {
            _vm.Companies = _db.Companies.ToList();
            _vm.Customers = _db.Customers.ToList();

            if (string.IsNullOrEmpty(search))
            {
                AllResults();
            }
            else
            {
                FilteredResults(search);
            }

            return View();
        }

        public PartialViewResult AllResults()
        {
            return PartialView(Json(_vm));
        }

        public PartialViewResult FilteredResults(string search)
        {
            return PartialView(Json(_vm));
        }

       // GET: Customer/Details/5
        public ActionResult Details(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            CustomerDb customer = _db.Customers.Find(id);
            if (customer == null)
            {
                return HttpNotFound();
            }
            return View(customer);
        }

        // GET: Customer/Add
        public ActionResult Add()
        {
            return View();
        }

        // POST: Customer/Add
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
       // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Add([Bind(Include = "ID,Obj_Data")] CustomerDb customer)
        {
            if (ModelState.IsValid)
            {
                _db.Customers.Add(customer);
                _db.SaveChanges();
                return RedirectToAction("Index");
            }

            return View(customer);
        }

        // GET: Clients/Update/5
        public ActionResult Update(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            CustomerDb customer = _db.Customers.Find(id);
            if (customer == null)
            {
                return HttpNotFound();
            }
            return View(customer);
        }

        // POST: Clients/Update/5
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Update([Bind(Include = "ID,Obj_Data")] CustomerDb customer)
        {
            if (ModelState.IsValid)
            {
                _db.Entry(customer).State = EntityState.Modified;
                _db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(customer);
        }

        // GET: Clients/Remove/5
        public ActionResult Remove(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            CustomerDb customer = _db.Customers.Find(id);
            if (customer == null)
            {
                return HttpNotFound();
            }
            return View(customer);
        }

        // POST: Clients/Remove/5
        [HttpPost, ActionName("Remove")]
        [ValidateAntiForgeryToken]
        public ActionResult RemoveConfirmed(int id)
        {
            CustomerDb customer = _db.Customers.Find(id);
            _db.Customers.Remove(customer);
            _db.SaveChanges();
            return RedirectToAction("Index");
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _db.Dispose();
            }
            base.Dispose(disposing);
        }
    }
}

从某种意义上说,我设法完成了这项工作:添加/更新客户信息的视图有一个 TextArea,我只需在其中添加 JSON 字符串。然后,在 Customer Index 视图中,我将 JSON 字符串反序列化为 Customer 对象并显示各个 Customer 值。然后,我使用 HTML/JavaScript 创建了一个带有表单字段的单独应用程序,以吐出我可以复制/粘贴到的 JSON 字符串。

如果只是我在使用它,那么就像粘贴到 JSON 字符串中一样,这完全没问题。假设我想为不同的用户设置我的应用程序,编辑一个缩小的 JSON 字符串很麻烦。

我想根据上面定义的 Customer 模型创建一个视图,并从 CustomerController 向数据库提交一个 JSON 字符串。有人可以指出我正确的方向吗?谢谢。

标签: asp.net-mvc-4

解决方案


我休息了几个星期,终于想出了一个答案。如果我理解发生了什么:

在 CustomerController 的 Update GET 操作中,我只是将输入 CustomerDb 的 Obj_Data 属性(在我的例子中是 JSON 字符串)反序列化为 Customer 对象。然后我将 Customer 对象传递回视图,到目前为止它运行良好(当然我绑定了相关的模型属性):

      // GET: Clients/Update/5
    public ActionResult Update(int? id)
    {
        if (id == null)
        {
            return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
        }
        CustomerDb customerDb = _db.Customers.Find(id);
        if (customerDb == null)
        {
            return HttpNotFound();
        }

        Customer customer = JsonConvert.DeserializeObject<Customer>(customerDb.Obj_Data); 
        return View(customer);
    }

    // POST: Clients/Update/5
    // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
    // more details see http://go.microsoft.com/fwlink/?LinkId=317598.
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Update([Bind(Include = "Id,Customer_Name,Customer_Company,Phones,Emails,Terms,Locations,Preferences,Exemptions")] Customer customer)
    {
        if (ModelState.IsValid)
        {
            _db.Entry(customer).State = EntityState.Modified;
            _db.SaveChanges();
            return RedirectToAction("Index");
        }
        return View(customer);
    }

有几件事我必须改变;对于客户模型,我必须用单独的字符串属性替换 Dictionary 属性。例如,我删除了电话词典并将其替换为主要、备用和传真字符串属性,而电子邮件词典现在是一个字符串。我确信有一种方法可以使用 Dictionary 属性,但是每次我使用它们测试所有内容时,我都会从它们那里得到一个 Null 引用异常。

然后,对各种控制器操作进行一些简单的编辑,以从数据库中添加和删除客户记录,它工作得非常好。

@Tetsuya Yamamoto,再次感谢您的帮助。


推荐阅读