El diccionario de parámetros contiene una entrada NULL para el parámetro ‘idEstatus’ – ASP.NET MVC

publicado por: Anonymous

Estoy haciendo un CRUD en ASP.NET MVC pero no queda mi método de edición, ya estoy probando varias formas de hacerlo y en mi último intento me aparece el siguiente error al dar click en el botón de editar.

El diccionario de parámetros contiene una entrada NULL para el
parámetro ‘idPerfil’ del tipo que no acepta valores NULL
‘System.Int32’ del método ‘System.Web.Mvc.ActionResult Update (Int32)’
en ‘AdministraZion.Controllers.PerfilesController’. Un parámetro
opcional debe ser un tipo de referencia, un tipo que acepta valores
NULL o debe declararse como parámetro opcional. Nombre del parámetro:
parámetros

Aquí dejo el código completo, espero que puedan ayudar con mi problema.

Esto es mi ViewModel (PerfilViewModel)

public class PerfilViewModel
{
    public int idPerfil { get; set; }
    public string descripcion { get; set; }
    public int idEstatus { get; set; }

    public IEnumerable<SelectListItem> Estatus { get; set; }
}

Este es mi Controller (PerfilesController)

public ActionResult Update(int idPerfil)
{
    PerfilViewModel vm = new PerfilViewModel();
    using (OrganizacionEntities2 db = new OrganizacionEntities2())
    {
        var t = db.catPerfiles.Find(idPerfil);
        vm.descripcion = t.descripcion;
        vm.idEstatus = (int)t.idEstatus;
        vm.idPerfil = t.idPerfil;
    }

    ViewBag.Estatus = db.catEstatus.Select(x => new SelectListItem
    {
        Text = x.descripcion,
        Value = x.idEstatus.ToString()
    }).ToList();

    return View(vm);
}

[HttpPost]
public ActionResult Update(PerfilViewModel vm)
{
    try
    {
        if (ModelState.IsValid)
        {
            using (OrganizacionEntities2 db = new OrganizacionEntities2())
            {
                var t = db.catPerfiles.Find(vm.idPerfil);
                t.descripcion = vm.descripcion;
                t.idEstatus = vm.idEstatus;

                db.Entry(t).State = System.Data.Entity.EntityState.Modified;
                db.SaveChanges();
                ViewBag.successMessage = "Estatus agregado con exito";
            }
            return Redirect("/Perfiles/");
        }

        ViewBag.Estatus = db.catEstatus.Select(x => new SelectListItem
        {
            Text = x.descripcion,
            Value = x.idEstatus.ToString()
        }).ToList();

        return View(vm);
    }
    catch (Exception ex)
    {
        ViewBag.successMessage = "Ocurrio un error, reintente por favor";
        throw new Exception(ex.Message);
    }
}

Ésta es mi View (Update)

@model AdministraZion.ViewModels.PerfilViewModel

@using (Html.BeginForm("Update", "Perfiles", FormMethod.Post))
{
    @Html.HiddenFor(d => d.idPerfil)
    <div class="box-body">
        <div class="form-group">
            <label for="inputDescripcion" class="form-control-label mt-3 ml-5">Descripción:</label>
            @Html.TextBoxFor(m => m.descripcion, "", new { @class = "form-control ml-5", style = "width:92%" })
    </div>
        <div class="form-group">
            <label for="inputEstatus" class="form-control-label ml-5">Estatus:</label>
            @Html.DropDownListFor(m => m.idEstatus, new SelectList(ViewBag.Estatus, "Value", "Text"), "--- Selecciona ---", new { @class = "form-control ml-5", style = "width:92%" })
        </div>
    </div>
    <div class="box-footer" style="text-align:center">
        <button type="submit" class="btn block btn-success mb-3" style="width: 30%" name="crear">Crear <i class="fa fa-plus-circle"></i></button>
    </div>
}

Mi Route.Config

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Login", action = "Index", id = UrlParameter.Optional }
        );
    }
}

Error de código fuente:

Se ha generado una excepción no controlada durante la ejecución de la
solicitud Web actual. La información sobre el origen y la ubicación de
la excepción pueden identificarse utilizando la excepción del
seguimiento de la pila siguiente.

Éste es el seguimiento de la pila:

[ArgumentException: El diccionario de parámetros contiene una entrada NULL para el parámetro ‘idPerfil’ del tipo que no acepta valores NULL ‘System.Int32’ del método ‘System.Web.Mvc.ActionResult Update(Int32)’ en ‘AdministraZion.Controllers.PerfilesController’. Un parámetro opcional debe ser un tipo de referencia, un tipo que acepte valores NULL o debe declararse como parámetro opcional.
Nombre del parámetro: parameters]
System.Web.Mvc.ActionDescriptor.ExtractParameterFromDictionary(ParameterInfo parameterInfo, IDictionary2 parameters, MethodInfo methodInfo) +527
System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary2 parameters) +91
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary2 parameters) +27
System.Web.Mvc.Async.<>c.b__9_0(IAsyncResult asyncResult, ActionInvocation innerInvokeState) +22
System.Web.Mvc.Async.WrappedAsyncResult2.CallEndDelegate(IAsyncResult asyncResult) +29
System.Web.Mvc.Async.WrappedAsyncResultBase1.End() +49
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult) +32
System.Web.Mvc.Async.AsyncInvocationWithFilters.b__11_0() +50
System.Web.Mvc.Async.<>c__DisplayClass11_1.b__2() +228
System.Web.Mvc.Async.<>c__DisplayClass7_0.b__1(IAsyncResult asyncResult) +10
System.Web.Mvc.Async.WrappedAsyncResult1.CallEndDelegate(IAsyncResult asyncResult) +10
System.Web.Mvc.Async.WrappedAsyncResultBase1.End() +49
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult) +34
System.Web.Mvc.Async.<>c__DisplayClass3_6.b__3() +35
System.Web.Mvc.Async.<>c__DisplayClass3_1.b__5(IAsyncResult asyncResult) +100
System.Web.Mvc.Async.WrappedAsyncResult1.CallEndDelegate(IAsyncResult asyncResult) +10
System.Web.Mvc.Async.WrappedAsyncResultBase1.End() +49
System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +27
System.Web.Mvc.<>c.b__152_1(IAsyncResult asyncResult, ExecuteCoreState innerState) +11
System.Web.Mvc.Async.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult) +29
System.Web.Mvc.Async.WrappedAsyncResultBase1.End() +49
System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +45
System.Web.Mvc.<>c.b__151_2(IAsyncResult asyncResult, Controller controller) +13
System.Web.Mvc.Async.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult) +22
System.Web.Mvc.Async.WrappedAsyncResultBase1.End() +49
System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +26
System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +10
System.Web.Mvc.<>c.b__20_1(IAsyncResult asyncResult, ProcessRequestState innerState) +28
System.Web.Mvc.Async.WrappedAsyncVoid1.CallEndDelegate(IAsyncResult asyncResult) +29
System.Web.Mvc.Async.WrappedAsyncResultBase1.End() +49
System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +28
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +9849569
System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step) +50
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +163

solución

En tu controlador, reemplaza:

public ActionResult Update(int idPerfil)

Por:

public ActionResult Update(int id)

El motivo está en route.config:

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}", //Aquí le estás diciendo que vas a recibir "id"
            defaults: new { controller = "Login", action = "Index", id = UrlParameter.Optional }
        );
    }
}

Si deseas otra alternativa, puedes usar el atributo [Route] en el action del controlador, de esta manera:

[Route("Update/{idPerfil:int}")]
public ActionResult Update(int idPerfil)

Lectura recomendada: https://devblogs.microsoft.com/aspnet/attribute-routing-in-asp-net-mvc-5/

Respondido por: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *