EdoRguez
EdoRguez

Reputation: 35

Model from PartialView to Controller returns null

I have a PartialView that recibes a Model ID and then when you click on the link sends the Model ID to the Controller. My problem was that there were 2 ways to send data from View to Controller but just only one worked for me. What's the reason why?

This worked perfectly for me

<a type="button" class="btn btn-primary" asp-controller="Dictionary" asp-action="Edit" asp-route-wordId="@Model"><i class="fas fa-edit"></i></a>

This one didn't work

<a type="button" class="btn btn-success" href="@Url.Action("Edit/" + Model)"><i class="far fa-list-alt"></i></a>

My question is why the last one didn't work and returned null if I am passing the Model ID to the URL

This is my full PartialView that receives a Model ID and works

@model int

<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">

<td style="width:150px">
    <div class="btn-group" role="group">
        <a type="button" class="btn btn-primary" asp-controller="Dictionary" asp-action="Edit" asp-route-wordId="@Model"><i class="fas fa-edit"></i></a>
    </div>
</td>

And this is my Controller Function that recibes the data

public async Task<IActionResult> Edit(int? wordId)
{
    if(wordId == null)
    {
        return NotFound();
    }

    var word = await _db.Dictionaries.FindAsync(wordId);
    if(word == null)
    {
        return NotFound();
    }

    return View(word);
}

Upvotes: 1

Views: 90

Answers (2)

jomsk1e
jomsk1e

Reputation: 3625

To answer your main question, the reason your 1st anchor is working is because the args are correct. For example:

<a asp-controller="Dictionary" asp-action="Edit" asp-route-wordId="1">Your link</a>

is equivalent to:

<a href="/Dictionary/Edit/1"></a>

That works!

The second will not work because you are misusing Url.Action, the method you are using is this Url.Action("Action")

Url.Action("Edit/" + Model) or  Url.Action("Edit/1") 

is searching for an action named: "Edit/1", which in your case will not be found.

so in your 2nd not working example

<a href="@Url.Action("Edit/" + Model)">Your Link</a>

is equivalent to:

<a href="null" />

In your case you should be using this in your anchor:

Url.Action("Edit", "Dictionary", new { id = @Model })

is equivalent to /Dictionary/Edit/1

so:

<a href="@Url.Action("Edit", "Dictionary", new { id = Model })">Your link</a>

Upvotes: 0

GregH
GregH

Reputation: 5459

The Url.Action overload you are using takes in an action name and you are passing something like /Edit/4 to it. You need to use the proper overload of the Url.Action method that allows you to specify route values.

It would look something like the following:

<a type="button" class="btn btn-success" href="@Url.Action("Edit/" + Model)"><i class="far fa-list-alt"></i></a>

to

<a type="button" class="btn btn-success" href="@Url.Action("Edit", new { wordId = Model } )"><i class="far fa-list-alt"></i></a>`

As a side note, your Edit action takes a nullable wordId which doesn't make much sense to me. Generally, if you're editing something then it has already been created and should always have an id. The only case I can think of where this makes sense is if the Edit action actually handles creating data as well as editing data in which case that would be perfectly valid.

Upvotes: 2

Related Questions