【问题标题】:Why is "Object reference not set to an instance of an object." error being raised here?为什么“对象引用未设置为对象的实例”。这里提出错误?
【发布时间】:2012-12-26 12:23:19
【问题描述】:

我正在开发一个 asp.net mvc web 应用程序,我有以下视图:-

@model MvcApplication4.Models.SelectedCustomers
<h3>Select Customers Detials</h3>
@using (Html.BeginForm("Export", null))
{    <table>
        <tr>
            <th>
                NAME @Html.CheckBox("IncludeName", true)
            </th>
            <th>
                Description @Html.CheckBox("IncludeDescription", true)
            </th>
            <th>
                Address @Html.CheckBox("IncludeAddress", true)
            </th>
        </tr>
        @foreach (var item in Model.Info) {
            <tr>
                <td>
                    @Html.DisplayFor(modelItem => item.ORG_NAME)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.LOGIN_URI)
                </td>
                <td>
                    @Html.DisplayFor(modelItem => item.SUPPORT_EMAIL)
                </td>
                @Html.HiddenFor(modelItem => item.ORG_ID)
            </tr>
        }
    </table>
    <p>
        @Html.ActionLink("Back","customer","Home") |
        <button type="submit" name="Format" value="xls">extract to excel</button> |
        <button type="submit" name="Format" value="csv">extract to text file</button>
    </p>
}

以及以下操作方法:-

[HttpPost]
        public ActionResult Export(ExportViewModel exportOptions, IList<AccountDefinition> accounts)
        {
          // var accounts = GetAccount();

            if (exportOptions.Format == "csv")
            {
                return accounts.AsCsvResult(exportOptions);
            }
            else if (exportOptions.Format == "xls")
            {
                return accounts.AsXlsResult(exportOptions);
            }

            throw new NotSupportedException(
                string.Format("Unsupported format: {0}", exportOptions.Format)
            );
        }

然后我在我的 AccountDefinition 模型中定义了以下方法:-

 public partial class AccountDefinition
    {
        public long ORG_ID { get; set; }
        public string ORG_NAME { get; set; }
        public string LOGIN_URI { get; set; }
        public string SUPPORT_EMAIL { get; set; }

        public virtual SDOrganization SDOrganization { get; set; }

    }
    public static class ActionResultextensions
    {
        public static ActionResult AsCsvResult(this IEnumerable<AccountDefinition> accounts, ExportViewModel exportOptions)
        {
            return new CsvResult(accounts, exportOptions);
        }

        public static ActionResult AsXlsResult(this IEnumerable<AccountDefinition> accounts, ExportViewModel exportOptions)
        {
            return new XlsResult(accounts, exportOptions);
        }
    }
}

然后我有以下模型类:-

1.

public class CsvResult : ExportAccountsResult
    {
        public CsvResult(IEnumerable<AccountDefinition> accounts, ExportViewModel exportOptions)
            : base(accounts, exportOptions)
        {
        }

        protected override string ContentType
        {
            get { return "text/csv"; }
        }

        protected override string Filename
        {
            get { return "accounts.csv"; }
        }        }

2,

 public class XlsResult : ExportAccountsResult
    {
        public XlsResult(IEnumerable<AccountDefinition> accounts, ExportViewModel exportOptions)
            : base(accounts, exportOptions)
        {
        }

        protected override string ContentType
        {
            get { return "application/vnd.ms-excel"; }
        }

        protected override string Filename
        {
            get { return "accounts.csv"; }
        }
    }

3.

public class ExportViewModel
    {
        public string Format { get; set; }
        public bool IncludeName { get; set; }
        public bool IncludeDescription { get; set; }
        public bool IncludeAddress { get; set; }

    }

4.

public abstract class ExportAccountsResult : ActionResult
    {
        protected ExportAccountsResult(IEnumerable<AccountDefinition> accounts, ExportViewModel exportOptions)
        {
            this.Accounts = accounts;
            this.ExportOptions = exportOptions;
        }

        protected IEnumerable<AccountDefinition> Accounts { get; private set; }
        protected ExportViewModel ExportOptions { get; private set; }

        protected abstract string ContentType { get; }
        protected abstract string Filename { get; }

        public override void ExecuteResult(ControllerContext context)
        {
            var response = context.HttpContext.Response;
            response.ContentType = ContentType;
            var cd = new ContentDisposition
            {
                FileName = this.Filename,
                Inline = false
            };
            response.AddHeader("Content-Disposition", cd.ToString());

            // TODO: Use a real CSV parser here such as https://github.com/JoshClose/CsvHelper/wiki/Basics
            // and never roll your own parser as shown in this oversimplified
            // example. Here's why: http://secretgeek.net/csv_trouble.asp
            using (var writer = new StreamWriter(response.OutputStream))
            {
                foreach (var account in this.Accounts)
                {
                    var values = new List<object>();
                    if (this.ExportOptions.IncludeName)
                    {
                        values.Add(account.ORG_NAME);
                    }
                    if (this.ExportOptions.IncludeDescription)
                    {
                        values.Add(account.LOGIN_URI);
                    }
                    if (this.ExportOptions.IncludeAddress)
                    {
                        values.Add(account.SUPPORT_EMAIL);
                    }
                    writer.WriteLine(string.Join(", ", values));
                }
            }
        }
    }

但是当我运行点击视图内的“提取到 excel”或“提取到文本文件”按钮时,我得到了以下异常:-

System.NullReferenceException was unhandled by user code
  HResult=-2147467261
  Message=Object reference not set to an instance of an object.
  Source=MvcApplication4
  StackTrace:
       at MvcApplication4.Models.ExportAccountsResult.ExecuteResult(ControllerContext context) in c:\Users\Administrator\Desktop\MvcApplication4\MvcApplication4\Models\ExportAccountsResult.cs:line 41
       at System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult)
       at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass1c.<InvokeActionResultWithFilters>b__19()
       at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation)
  InnerException:

ExportAccountsresults.cs 中的以下代码:-

 foreach (var account in this.Accounts)
                {

:::UPDATED:::

我已将我的观点更新为以下内容:-

@model MvcApplication4.Models.SelectedCustomers



<h3>Select Customers Detials</h3>

    @using (Html.BeginForm("Export", null))
    {
        Int32 c = -1;
        <table>
            <tr>
                <th>
                    NAME @Html.CheckBox("IncludeName", true)
                </th>
                <th>
                    Description @Html.CheckBox("IncludeDescription", true)
                </th>
                <th>
                    Address @Html.CheckBox("IncludeAddress", true)
                </th>
            </tr>
            @foreach (var item in Model.Info) {
                c++;
                <tr>
                    <td>
                        @Html.DisplayFor(modelItem => item.ORG_NAME)
                    </td>
                    <td>
                        @Html.DisplayFor(modelItem => item.LOGIN_URI)
                    </td>
                    <td>
                        @Html.DisplayFor(modelItem => item.SUPPORT_EMAIL)
                    </td>

                     <td>@Html.Hidden(String.Format("Info[{0}].ORG_ID", c), item.ORG_ID)</td>
                </tr>
            }
        </table>

        <p>
            @Html.ActionLink("Back","customer","Home") |
            <button type="submit" name="Format" value="xls">extract to excel</button> |
            <button type="submit" name="Format" value="csv">extract to text file</button>
        </p>
    }

我的操作方法如下:-

  [HttpPost]
        public ActionResult Export(ExportViewModel exportOptions, SelectedCustomers sc)
        {
          // var accounts = GetAccount();
           var accounts = sc.Info.ToList();
            if (exportOptions.Format == "csv")
            {
                return accounts.AsCsvResult(exportOptions);
            }
            else if (exportOptions.Format == "xls")
            {
                return accounts.AsXlsResult(exportOptions);
            }

            throw new NotSupportedException(
                string.Format("Unsupported format: {0}", exportOptions.Format)
            );
        }

现在 csv 文件将打开,但它将是空的,并且每条记录都不会包含“,”,例如,如果 excel 表或文本文件中应该有 7 条记录,那么 .csv 文件将具有以下无数据:-

, , 
, , 
, , 
, , 
, , 
, , 
, , 

【问题讨论】:

  • 这似乎意味着 this.Accounts 为 Null。请求中没有任何内容允许绑定到 IEnumerable 帐户。
  • 谢谢你能检查我对原始问题的更新
  • 可以贴一行html对应一个客户吗?
  • 我重新提出我的问题:生成的 html 中隐藏标签的名称是什么。它们应该是 SelectedCustomers.Info[x].ORG_ID,其中 x 是从 0 到 N-1 的数字,其中 N 是客户数量。
  • @JohnPeter,这是因为您使用的是 Display 而不是 Textbox。传输的唯一值是 ORG_ID。您应该在存储之前从 Ids 中恢复数据。

标签: c# asp.net .net razor


【解决方案1】:

以下运行(请在视图中查看 HiddeFor 和 Hidden 之间的区别):

控制器

namespace SomeApp.Controllers {
public class TestModel {        
    public IEnumerable<TestModelItem> Items { get; set; }
}

public class TestModelItem {
    public int Id { get; set; }
    public String Name { get; set; }
}
public class TestsController : Controller {

    public ActionResult Index() {
        TestModel tm = new TestModel {
            Items = new List<TestModelItem> {
                new TestModelItem { Id = 1, Name = "first"},
                new TestModelItem { Id = 2, Name = "second"}
            }
        };

        return View(tm);
    }

    [HttpPost]
    public ActionResult Index(TestModel tm) {
        return View(tm);
    }

}
}

还有风景

@model SomeApp.Controllers.TestModel
@{
    Layout = null;
    Int32 c = -1;
}

<!DOCTYPE html>

<html>
<head>
    <title>Index</title>
</head>
<body>
    <form method="post">
        <table>
        @foreach (var i in Model.Items) {
            c++;
            <tr>
                @*<td>@Html.HiddenFor(x => i.Id)</td>*@
                <td>@Html.Hidden(String.Format("Items[{0}].Id", c), i.Id)</td>
                <td>@Html.DisplayFor(x => i.Name)</td>
            </tr>
        }
        </table>
        <button type=submit>go</button>
    </form>
</body>
</html>

【讨论】:

  • thnak 你能检查我的 :::UPDATED::: 部分文件现在将打开但没有数据。
【解决方案2】:

问题是IList&lt;AccountDefinition&gt; 不能转换为IEnumerable&lt;AccountDefinition&gt;,所以要么在这里接收IEnumerable&lt;T&gt;

public ActionResult Export(ExportViewModel exportOptions, IList<AccountDefinition> accounts)

或将其他所有内容更改为IList&lt;T&gt;


另一种方法是:

public ActionResult Export(ExportViewModel exportOptions, IList<AccountDefinition> accounts)
{
    var enumerableAccounts = accounts.AsEnumerable();

    if (exportOptions.Format == "csv")
    {
        return enumerableAccounts.AsCsvResult(exportOptions);
    }
    else if (exportOptions.Format == "xls")
    {
        return enumerableAccounts.AsXlsResult(exportOptions);
    }

    throw new NotSupportedException(
        string.Format("Unsupported format: {0}", exportOptions.Format)
    );
}

【讨论】:

  • 感谢您的回复,我将操作方法​​更改为接收 IList 帐户,但我仍然收到以下错误:-“对象引用未设置为对象的实例。”
  • 我也试过你的操作方法,但仍然出现同样的错误。
  • @JohnPeter,实际上你需要从动作方法一直到相同的类型。因此,将您在操作方法中收到的任何内容转换为IEnumerable&lt;T&gt;,并保持其他所有内容不变。根据您的两个 cmets,感觉堆栈的其余部分现在也发生了一些变化。我敢肯定,自从您提出要求以来,您一直在尝试不同的事情。
  • @JohnPeter,我确定你是否在扩展方法中检查了 accounts 的值,它是 null - 你能验证一下吗?
  • 嗯...IList&lt;AccountDefinition&gt; 怎么不能转换成IEnumerable&lt;AccountDefinition&gt;IList&lt;T&gt; 继承自 IEnumerable&lt;T&gt;
猜你喜欢
  • 2021-09-24
  • 2019-03-20
  • 2014-06-04
  • 1970-01-01
  • 2011-07-09
  • 2012-08-31
  • 2011-11-21
  • 2012-10-01
  • 1970-01-01
相关资源
最近更新 更多