0

i have looked around and seen that alot of people have had this problem. However mine is not exactly the same. While the other problems are typically solved by using correct overloads of the ActionLink Method, and fixed by making sure that the recieved object type in the method is correct, this is not the came.

In this example code, the variables are all set correct according to all other sources, however the user object recieved in the method is always null.

What i have done:

  • Checked if the object put onto the ActionLink has data (it does)
  • Checked if the Type of the object i received is correct, along with the one i send
  • Tried using Ajax ActionLink and HttpPost Method instead

Here is the code first from backend and then frontend

public void DeleteUser(User user)
    {
        using (EFEntity context = new EFEntity())
        {
            context.User.Attach(user);
            context.User.Remove(user);
            context.SaveChanges();
            Response.Redirect("~/Home/someView");
        }
    }

Action Link Front end:

foreach (User user in Model.userList)
{
    <tr>
        <td>
            @{
            number = number + 1;
            }
            @number
        </td>
        <td>@user.Gid</td>
        <td>@user.Name</td>
        <td>@user.Email</td>
        <td>@user.Permissions.Perm</td>
        <td>@user.LastUpdated</td>
        <td>
                @Html.ActionLink("Delete", "DeleteUser", "Service", user, new { @class = "btn btn-danger" })
        </td>
    </tr>
}
Ilya Chumakov
  • 23,161
  • 9
  • 86
  • 114
somedeveloper
  • 83
  • 1
  • 4
  • 1
    You should not be passing a complex in an `ActionLink()`. If the objects has numerous properties you could easily exceed the query string and throw an exception (and there the ugly query string it creates). You should just be passing the `ID` property of the user. –  Jan 14 '16 at 09:28
  • 1
    And you should not even be using an action link - your modifying data so it should be a POST - currently its added the users browser history and can be easily navigated to again. At best this will mean making unnecessary database calls to delete something which does not currently exist, and at worst may throw an exception. Strongly recommend you follow normal practice. –  Jan 14 '16 at 09:31
  • @StephenMuecke Please elaborate about the repost and browser history, it is not clear what you mean. When u click this button, it refreshes the page, so you do not have the option of deleting the same thing twice. Or have i mis interpreted what you mean? – somedeveloper Jan 14 '16 at 10:07
  • 2
    Its a link. Any use can type it in the address bar. And when the user clicks the link, your awful address will be added to their browser history which means they could easily open their browser history page and click on it again (resulting in deleting something which no longer exists - and maybe throw an exception) You should be generating a form in the loop - @Html.BegnForm("DeleteUser", "Service", new { ID = user.ID }, FormMethod.Post, null)) { }` and change the method to `[HttpPost] public ActionResult DeleteUser(int ID)` –  Jan 14 '16 at 10:15
  • Thanks for the elaboration, that is some useful information. I will opt to use Ajax link instead and post method, however i would still pass the information to be deleted as an object instead of just an ID probably, i don't see why it is a significant downside doing that. – somedeveloper Jan 14 '16 at 11:59
  • 2
    If you doing a post, then there is no downside passing the model (other that the insignificant extra data sent across the wire) however its unnecessary. All that is required to delete an entity is the ID - for example [this answer](http://stackoverflow.com/questions/17723276/delete-a-single-record-from-entity-framework) –  Jan 14 '16 at 12:06
  • Thank you, its always great learning new things and becoming more conscious of these choices in coding. In this case i don't think it has any impact at all, since the object isnt very large, and not a great deal of people will be using it. But in the spirit of extra knowledge i've attained i will make it delete by id :) – somedeveloper Jan 14 '16 at 12:29
  • As a final note, its common to display a confirm dialog before deleting - something like [this answer](http://stackoverflow.com/questions/34690155/action-method-didnt-worked-with-httppost-attribute-in-asp-net-mvc/34690709#34690709) –  Jan 14 '16 at 22:27

1 Answers1

0

I figured the problem out, its a bit of a weird one, it is not too hard to fix.

Inspecting the user object' closer and looking at the source code in the browser, you could see some kind of string on the object, that had a bunch of numbers in it aswell as something with "dynamic proxy".

Through further research i learned the reason the object was always null was because the object were being generated with Dynamic Proxy options. This had for some reason been enabled by itself somehow, any only on this specific EF model.

The fix was to disable the usage of dynamic proxies globally in entity framework.

How to do it:

Go to your Model.edmx -> Model.Context.tt -> Model.Context.cs

Her you're going to add the line "Configuration.ProxyCreationEnabled = false;" inside the public method that is your entity model.

Code before:

public partial class EFEntity: DbContext
    {
        public EFEntity()
            : base("name=EFEntity")
        {
        }
        ......
    }

Code After:

public partial class EFEntity: DbContext
        {
            public EFEntity()
                : base("name=EFEntity")
            {
                Configuration.ProxyCreationEnabled = false;
            }
            ......
        }

This should globally disable proxy creation and should fix this specific problem.

Hope it helps someone, I've struggled finding out what was wrong for days

somedeveloper
  • 83
  • 1
  • 4
  • _"The fix was to disable the usage of dynamic proxies globally in entity framework"_ - no, the **proper** fix is to use viewmodels instead of Entity Framework models. You also wouldn't have to spend days on this issue if you'd have looked at the generated HTML. :) – CodeCaster Jan 14 '16 at 11:39
  • I don't think its necessary to return the viewmodel, when all u want to know is what is to be deleted. Your comment on how long i took to find out the issue is not very constructive, can u keep it on topic please. Whatever code you think is a better way to do things is not so relevant as that was not the issue here. In this case even using a view model would probably still cause the same issues, seeing as all the user objects from EF were being generated with dynamic proxies. – somedeveloper Jan 14 '16 at 12:19
  • I just posted this incase anyone else had this problem, seeing as i couldn't find any help on it when searching for it. so either it fixes their problem or it leads them on the right track – somedeveloper Jan 14 '16 at 12:21
  • The "answer" to _"I tried to hammer this nail into a piece of wood with a shoe, now the nail is bent. How can I straighten it?"_ is also _"You can straighten the nail by bending it back with pliers"_. However, both question and answer do not address the real problem: _"People generally insert nails into things with a hammer, it's the better tool for that"_. You should not expose your data layer to your view layer, period. It introduces problems like the one you had here. People still can need lazy loading and proxy creation. – CodeCaster Jan 14 '16 at 12:39
  • Also, how long you spent on this problem is irrelevant, so can you keep your answer ontopic please. I was just pointing out that _"Why doesn't my model bind"_ is easily troubleshooted by looking at the HTML that gets generated. – CodeCaster Jan 14 '16 at 12:40
  • I appreciate the wisdom you bring to the table, i just think that you put unnecessarily much weight on the fact that i shouldn't have spend days on this. I only shared it, in case someone else had the same problem. Because even if its easy for you, maybe it is not so much for others. If you search this problem you only find stuff where other things was the cause of the problem, never where this(proxy) was the cause of the problem. And so it might help others who is searching. So i don't think how long i spent solving the problem has any importance at all. But thanks for your contribution. – somedeveloper Jan 15 '16 at 07:04