0

I have the following view part:

<div class="editor-label">
    @Html.LabelFor(model => model.Type)
</div>
<div class="editor-field">
    @Html.DropDownListFor(model => model.Type, ElangWeb.Helpers.ModelHelpers.GetExerciseTypes())
</div>

I want to have a link which will generate some partialview based on my model's Type property which is an Enum (I return different partial views based on the type), I've added the following link:

@Ajax.ActionLink("AddExerciseItem", 
                        "AddExerciseItem",
                        "Exercise",
                        new { type=@Model.Type},
                        new AjaxOptions() { HttpMethod="GET", InsertionMode = InsertionMode.InsertBefore, UpdateTargetId="ExerciseItems"})

My controller action is defined as follows:

public ActionResult AddExerciseItem(ExerciseType type)
{

  return PartialView("ExerciseItemOption", new ExerciseItemOption());
}

I however does not work because I have the exeption "Object reference not set to an instance of an object" for my Model. How to resolve this issue?

niao
  • 4,972
  • 19
  • 66
  • 114

1 Answers1

3

You could use a normal link:

@Html.ActionLink(
    "AddExerciseItem", 
    "AddExerciseItem", 
    "Exercise", 
    null, 
    new { id = "add" }
)

that you could unobtrusively AJAXify:

// When the DOM is ready
$(function() {
    // Subscribe to the click event of the anchor
    $('#add').click(function() {
        // When the anchor is clicked get the currently
        // selected type from the dropdown list.
        var type = $('#Type').val();

        // and send an AJAX request to the controller action that 
        // this link is pointing to:
        $.ajax({
            url: this.href,
            type: 'GET',
            // and include the type as query string parameter
            data: { type: type },
            // and make sure that you disable the cache because some
            // browsers might cache GET requests
            cache: false,
            success: function(result) {
                // When the AJAX request succeeds prepend the resulting
                // markup to the DOM the same way you were doing in your
                // AJAX.ActionLink
                $('#ExerciseItems').prepend(result);
            }
        });
        return false;
    });
});

Now your AddExerciseItem controller action could take the type parameter:

public ActionResult AddExerciseItem(string type)
{
    ...
}
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • That's an excellent answer but I'm wondering, is there any reason why I can't do this using @Ajax.ActionLink? – niao Jan 25 '13 at 12:15
  • Yes, of course that there is a reason. The @Ajax.ActionLink helper forces you to supply all parameters that will be sent to the server. Except that as you know the Ajax.ActionLink helper runs on the server and at this stage there's no value for the Type parameter in the dropdown simply because the user might change it much later and you will have to take this change into account and get the correct value from this dropdown at the moment the link is clicked and not at the moment when the page is rendered. – Darin Dimitrov Jan 25 '13 at 12:16
  • This works fine, however when I try to return a PartialView, it's indeed returned but ExerciseItems are is not appended but instead by PartialView is shown in an empty page – niao Jan 25 '13 at 14:57
  • This could happen if you have javascript errors. Check your js console. – Darin Dimitrov Jan 25 '13 at 14:59
  • I know what's happening. The Action "AddExerciseItem" which is registered for the ActionLink is executed twice. – niao Jan 25 '13 at 15:10
  • It should be an `Html.ActionLink` (as shown in my answer) and not `Ajax.ActionLink`. – Darin Dimitrov Jan 25 '13 at 15:11
  • yes it is. it is as follows: @Html.ActionLink("Add Exercise Item", "AddExerciseItem", "Exercise", null, new { id = "AddExerciseItem" }) – niao Jan 25 '13 at 15:13
  • Then why do you get 2 AJAX requests? – Darin Dimitrov Jan 25 '13 at 15:13
  • It seems that the AJAX request is executed once. Secondly it's a request invoked by the button itself because for the second time my type parameter in the controller is null. – niao Jan 25 '13 at 15:16
  • I don't quite understand what button you are talking about. Anyway, did you solve the problem? – Darin Dimitrov Jan 25 '13 at 15:17
  • I'm sorry it is of course @Html.ActionLink. No I did not yet solve the problem. – niao Jan 25 '13 at 15:19
  • do you maybe have other idea why the problem described in my comments (double execution of the controller's action) occurs? – niao Jan 28 '13 at 11:00
  • No, I have no idea. Maybe you have some other javascript code tat you haven't shown that is calling it or maybe some form is being submitted. Hard to tell without knowing your code. – Darin Dimitrov Jan 28 '13 at 11:54
  • May it be because I have my @@Html.ActionLink inside @using (Html.BeginForm()) {...} ? – niao Jan 29 '13 at 20:11
  • No, that's not the reason. An ActionLink generates an anchor tag which is not related to any form. It doesn't really matter if it is inside a form or not. – Darin Dimitrov Jan 29 '13 at 21:11
  • That's the same as `return false` from the `click` handler. The only difference is that if you have an error in your javascript code the return false statement might never be reached, whereas if you call e.preventDefault in the beginning of the callback it will prevent the action from executing despite the javascript error. Look at your javascript console to find your error. – Darin Dimitrov Jan 31 '13 at 21:26