开发者

Asp.Net MVC 2 - Weird behavior: RedirectToAction and ValidationSummary not working

I've been working with MVC 2 for awhile and ive done ReturnToAction as well as ValidationSummary - but this is a little different in that my "submit" buttons are controls by javascript/JQuery - i debug the action and it does go into the correct Controller Action but once it passes over RedirecToAction, nothing happens....

My second problem is that my ValidationSummary fails to show - i run a test and when it returns a View when ModelState is invalid - nothing shows up

Is it a problem with my buttons/forms/submit/JQuery?

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">      

<script type="text/javascript">  
    $(function () {  

            /*stuff here to setup some JQuery Sortable lists*/  

        $("#UpdateButton").click(function () {  

            //create Arrays from JQuery Sortable List and go to Action for "submit"                   //processing  

            $.ajax({  
                url: '/Admin/SortedLists/',  
                data: { items: editedRoles, items2: $("#deleteList").sortable('toArray') },  
                type: 'POST',  
                traditional: true  
            });  
        });  

            //go to Action and just "Reload" the page  
        $("#UndoButton").click(function () {  
            //reload the page  
                var url = '<%= Url.Action("EditRoles") %>';                
            window.location.href = url;  
        });  

        $("#roleList, #deleteList").disableSelection();  
        $("#deleteList").hide();  
    });  


    function addNewRole() {  
        var text = $("#New_Role").val();  

        $("#roleList").append('<li id="-1~' + text + '" class="ui-state-default">' +  
                              '<span class="ui-icon ui-icon-closethick"></span>' +  
        //                    '<span class="ui-icon ui-icon-arrowthick-2-n-s"></span>' +  
                              '<input id="-1" type="text" value="' + text + '" />' +                                    
                              '</li>');  
        $("#roleList").sortable('refresh');  
    }  
</script>  

<%= Html.ActionLink("Back", "Index") %>      

<% using (Html.BeginForm()) { %>    
    <br />       
    <%= Html.Encode(ViewData["Message"]) %>  
    <%=Html.ValidationSummary(true, "Edit was unsuccessful. Please correct the errors and try again.")%>  
    <div class="demo">         

        <%=Html.TextBox("New Role", "New Role")%>  
        <a href="javascript:addNewRole()"> Add</a>  

        <br />  
        <br />  
        <ul id="roleList" class='droptrue'>  

         //create an开发者_C百科 unordered list with textboxes and a close icon  
            <%  
           foreach (var item in Model.Roles)  
           {%>                                   
             <li class="ui-state-default" id="<%=Html.AttributeEncode(item.Id)%>~<%=Html.AttributeEncode(item.Name)%>"><span class="ui-icon ui-icon-closethick"></span><%=Html.TextBox(item.Id.ToString(), item.Name, new {@id = item.Id})%></li>                                                                              

         <% } %>        
        </ul>  

        <ul id="deleteList" class='droptrue'>  
        </ul>         

        <br />  

        </div>        

            <input id="UpdateButton" type="submit" name="submitButton" value="Update" /><%= Html.ValidationMessage("UpdateButton", "*") %>                  
            <input id="UndoButton" type="submit" name="submitButton" value="Undo" />              

<% } %>  

And the Controller looks like this:

public AdminController()  
    {  
        var wrapper = new ModelStateWrapper(ModelState);  
        _rolesService = new RolesService(new RolesRepository(), new RolesValidator(wrapper, new DateValidator(wrapper)));  
    }  

    public ActionResult Index()  
    {  
        return View();  
    }  

    public ActionResult EditRoles()  
    {  
        var roles = _rolesService.FetchAllRoles();  
        return View(new AdminEditRolesViewModel(roles));  
    }  

    [HttpPost]  
    public ActionResult SortedLists(List<string> items, List<string> items2)  
    {  
        var roles = _rolesService.BuildRolesFromList(items);  
        var deletedRoles = _rolesService.BuildRolesFromList(items2);  

        //The Services have contain the ModelState, this is where errors happen  
        //ValidationSummary doesnt show anything  
        if (_rolesService.EditRoles(roles) == false)  
        {  
            roles = _rolesService.FetchAllRoles();  
            return View("EditRoles", new AdminEditRolesViewModel(roles));  
        }  

        if (_rolesService.DeleteRoles(deletedRoles) == false)  
        {  

            roles = _rolesService.FetchAllRoles();  
            return View("EditRoles", new AdminEditRolesViewModel(roles));  
        }  

        _rolesService.Save();  

        //This RedirecToAction is passed, but doesnt actually go to my Index()  
        return RedirectToAction("Index");  

    }  

My Services handle things like validation, I pass it the ModelState and a ModelStateDictionary wrapper and add errors - am i adding errors incorrectly?

public bool DeleteRoles(IEnumerable<Role> deletedRoles)  
{  
    //some work, if fails add error  

    _validator.AddError("UpdateButton",  
        "Role: " + role.Name +  
        " can not be deleted because Employees still use this";

    return _validator.IsValid();  
} 

Thanks for any help - this is driving me up the wall


It is normal for it to pass over RedirectToAction() in the debugger. It won't actually do the redirect until it returns from the method. But your controller action is running. You're just not seeing anything because your front-end presentation layer which is the web page isn't doing anything to handle the callback that your ajax call sets. To solve that, you'll create a callback function like so:

        $.ajax({  
            url: '/Admin/SortedLists/',  
            data: { items: editedRoles, items2: $("#deleteList").sortable('toArray') },  
            type: 'POST',  
            traditional: true,
            success: function(data) {
                alert(data);
            }
        });

Obviously you'll do something more useful with 'data', but we're just displaying it for now.

The validatorSummary isn't showing because the method that is creating it is not your action upon POST. It is being 'erased' by the RedirectToAction. To solve that you'll use something like this instead:

return View("~/Views/Home/Index.aspx", model);

This will send the user directly there and will preserve your modelstate, including validations.


I think you have a couple of problems.

  • Redirect not happening the way you expect

I'm thinking this is because your posting the form asynchronously with the $.ajax() call, but you're not handling the return values. A RedirectToAction returns a URL and an HTTP status code of 302 (might be 301, I forget), that tells the browser to request the URL returned. Your controller action is returning a HTTP redirect to an async javascript call, which isn't handling it.

You need to either change your submission JavaScript or handle the return value with something like .ajaxSuccess().

  • ValidationSummary not showing.

Your ValidationSummary isn't showing for two reasons. The first is because of the ajax return thing I just described. The second is you "lost" the ModelState when you did the RedirectToAction. Unless you explicitly handle the ModelState transfer (typically by exporting it to TempData and importing it in the target action), it will be lost when you redirect.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜