【发布时间】:2020-07-21 23:10:42
【问题描述】:
我在使 Delete 方法 (MVC) 中的代码崩溃时遇到了一些困难。这是我的 ProductItem 控制器类中的两个方法。 “删除”工作正常,但我收到一条错误消息,当我单步执行时,我注意到它下面的 DeleteConfirmed 获得了 prodID 的空值(itemID 正常传递)。我很难解决这个问题,因为我不知道 DeleteConfirmed 方法是如何被“调用”的,也不知道值是如何传入(或应该传入)的,所以我不知道要跟踪或逐步执行什么.
编辑:我从 itemID 和 productID 的两个参数中删除了 nullable,现在它甚至没有到达 DeleteConfirmed,我明白了:
[ArgumentException: The parameters dictionary contains a null entry for parameter 'prodID' of non-nullable type 'System.Int32' for method 'System.Threading.Tasks.Task`1[System.Web.Mvc.ActionResult] DeleteConfirmed(Int32, Int32)' in 'Memberships.Areas.Admin.Controllers.ProductItemController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.
Parameter name: parameters]
System.Web.Mvc.ActionDescriptor.ExtractParameterFromDictionary(ParameterInfo parameterInfo, IDictionary`2 parameters, MethodInfo methodInfo) +527
System.Web.Mvc.Async.<>c__DisplayClass20_0.<BeginExecute>b__0(ParameterInfo parameterInfo) +19
System.Linq.WhereSelectArrayIterator`2.MoveNext() +58
System.Linq.Buffer`1..ctor(IEnumerable`1 source) +196
System.Linq.Enumerable.ToArray(IEnumerable`1 source) +79
System.Web.Mvc.Async.TaskAsyncActionDescriptor.BeginExecute(ControllerContext controllerContext, IDictionary`2 parameters, AsyncCallback callback, Object state) +152
System.Web.Mvc.Async.<>c__DisplayClass8_0.<BeginInvokeAsynchronousActionMethod>b__0(AsyncCallback asyncCallback, Object asyncState) +28
System.Web.Mvc.Async.WrappedAsyncResult`1.CallBeginDelegate(AsyncCallback callback, Object callbackState) +14
System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +128
System.Web.Mvc.Async.AsyncControllerActionInvoker.BeginInvokeAsynchronousActionMethod(ControllerContext controllerContext, AsyncActionDescriptor actionDescriptor, IDictionary`2 parameters, AsyncCallback callback, Object state) +179
System.Web.Mvc.Async.AsyncControllerActionInvoker.BeginInvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters, AsyncCallback callback, Object state) +45
System.Web.Mvc.Async.AsyncInvocationWithFilters.InvokeActionMethodFilterAsynchronouslyRecursive(Int32 filterIndex) +87
System.Web.Mvc.Async.AsyncInvocationWithFilters.InvokeActionMethodFilterAsynchronouslyRecursive(Int32 filterIndex) +629
System.Web.Mvc.Async.<>c__DisplayClass7_0.<BeginInvokeActionMethodWithFilters>b__0(AsyncCallback asyncCallback, Object asyncState) +58
System.Web.Mvc.Async.WrappedAsyncResult`1.CallBeginDelegate(AsyncCallback callback, Object callbackState) +14
System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +128
System.Web.Mvc.Async.AsyncControllerActionInvoker.BeginInvokeActionMethodWithFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters, AsyncCallback callback, Object state) +197
System.Web.Mvc.Async.<>c__DisplayClass3_1.<BeginInvokeAction>b__0(AsyncCallback asyncCallback, Object asyncState) +640
System.Web.Mvc.Async.WrappedAsyncResult`1.CallBeginDelegate(AsyncCallback callback, Object callbackState) +14
System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +128
System.Web.Mvc.Async.AsyncControllerActionInvoker.BeginInvokeAction(ControllerContext controllerContext, String actionName, AsyncCallback callback, Object state) +346
System.Web.Mvc.<>c.<BeginExecuteCore>b__152_0(AsyncCallback asyncCallback, Object asyncState, ExecuteCoreState innerState) +27
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallBeginDelegate(AsyncCallback callback, Object callbackState) +30
System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +128
System.Web.Mvc.Controller.BeginExecuteCore(AsyncCallback callback, Object state) +494
System.Web.Mvc.<>c.<BeginExecute>b__151_1(AsyncCallback asyncCallback, Object callbackState, Controller controller) +16
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallBeginDelegate(AsyncCallback callback, Object callbackState) +20
System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +128
System.Web.Mvc.Controller.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state) +403
System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state) +16
System.Web.Mvc.<>c.<BeginProcessRequest>b__20_0(AsyncCallback asyncCallback, Object asyncState, ProcessRequestState innerState) +54
System.Web.Mvc.Async.WrappedAsyncVoid`1.CallBeginDelegate(AsyncCallback callback, Object callbackState) +30
System.Web.Mvc.Async.WrappedAsyncResultBase`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +128
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +427
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +48
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +16
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +105
System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step) +50
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +163
// GET: Admin/ProductItem/Delete/5
public async Task<ActionResult> Delete(int? itemID, int? productID)
{
if (itemID == null || productID == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Product_Item product_Item = await GetProductItem(itemID, productID);
if (product_Item == null)
{
return HttpNotFound();
}
return View(await product_Item.Convert(db));
}
// POST: Admin/ProductItem/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<ActionResult> DeleteConfirmed(int itemID, int prodID)
{
Product_Item product_Item = await GetProductItem(itemID, prodID);
db.Products_Items.Remove(product_Item);
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
根据要求:视图模型
using Memberships.Entities;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web;
namespace Memberships.Areas.Admin.Models
{
public class ProductItemModel
{
[DisplayName("Product ID")]
public int ProductID { get; set; }
[DisplayName("Item ID")]
public int ItemID { get; set; }
[DisplayName("Product")]
public string ProductTitle { get; set; }
[DisplayName("Item")]
public string ItemTitle { get; set; }
public ICollection<Product> Products { get; set; }
public ICollection<Item> Items { get; set; }
}
}
public static async Task<ProductItemModel> Convert
(this Product_Item productItem, ApplicationDbContext db, bool addListData=true)
//Only fill collections if the parameter passed in is true
{
var model = new ProductItemModel
{
ItemID = productItem.ItemID,
ProductID = productItem.ProductID,
Items = addListData ? await db.Items.ToListAsync() : null,
Products = addListData ? await db.Products.ToListAsync() : null,
ItemTitle = (await db.Items.FirstOrDefaultAsync(i => i.ID.Equals(productItem.ItemID))).Title,
ProductTitle = (await db.Products.FirstOrDefaultAsync(p => p.ID.Equals(productItem.ProductID))).Title
};
return model;
}
private async Task<Product_Item> GetProductItem(int? item, int? prod)
{
try
{
int itemID = 0, prodID = 0;
int.TryParse(item.ToString(), out itemID);
int.TryParse(prod.ToString(), out prodID);
var productItem = await db.Products_Items.FirstOrDefaultAsync
(
pi => pi.ProductID.Equals(prodID) && pi.ItemID.Equals(itemID)
);
return productItem;
}
catch {return null;}
}
【问题讨论】:
-
没有“堆栈跟踪?”你需要知道谁在打电话。毫无疑问,这种错误是由调用例程中的问题引起的。 (这就是为什么这些方法特别注意 Null ...)
-
好吧,如果 ItemID 和 prodID 不能为 NULL,那么您应该将它们的签名更改为不可为空的参数,即删除 ?分数。如果它们可以为 NULL,那么您只需要在调用 Remove() 之前进行检查,因为...它们可以根据您的设计为 NULL。
-
很抱歉给您带来了困惑。 ConfirmDelete 的可为空参数是一个错误。我解决了这个问题,但现在我得到了一个完全不同的错误(我在上面粘贴了),我还将粘贴堆栈跟踪。不幸的是,我不明白我在看什么:
-
@DavidLiang 两个参数都应该是非空的,我更改了参数以反映这一点。我可以在 .Remove() 处检查它们,但无论如何它们都不应该为空。错误已更改为“参数字典包含参数'prodID'的空条目”所以问题是它仍然传入一个空值(问题是我不知道“它”是什么)我正在尝试弄清楚它为什么这样做以及从哪里“调用”这个方法。
-
@DavidBritz:如果您可以向我们展示视图模型(
product_Item.Convert(db)生成的内容)以及您如何在视图中构建表单,这可能会有所帮助。
标签: asp.net-mvc entity-framework model-view-controller