简体   繁体   中英

Is it right to generate the javascript using C# in ASP.NET MVC view page?

[Sorry for long question but it is necessary to explain the problem]

I am working on a learning website and it is supposed to show a list of messages to user if there are any. Something like this:

替代文字

When user presses close button, that message must be marked "read" and should not be shown next time. Following code is used to generate those messages:

<% foreach (var m in Model.UserMessages) { %>
    <div class="um" id="m<%=Html.AttributeEncode(m.ID) %>">
        <p class="mh"><%= Html.Encode (String.Format ("From {0} ({1})", m.From, m.Sent)) %></p>
        <p><%= Html.Encode (m.Text) %></p>
        <% using (Html.BeginForm ("CloseMessage", "Home", new { id = m.ID })) { %>
            <input type="submit" value="Close<%= Html.AttributeEncode (m.ID) %>" id="c<%= Html.AttributeEncode (m.ID) %>"/>
        <% } %>
    </div>
<% } %>

After that, following the guidelines, I added the support of http post method in controller which marks the message as read and then refreshes the view (to handle disabled JavaScript):

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult CloseMessage (int id) {
    using (var dl = new DL ()) {
        dl.MarkAsRead (id);
    }

    if (Request.IsAjaxRequest ()) {
        return new EmptyResult ();
    }
    else {
        return RedirectToAction ("Index");
    }
}

Then I wanted to add JavaScript support such that only the message goes away (using jQuery). But the problem is that I am generating the buttons and messages programmatically.

So ended up with a weird looking javascript code in viewpage:

<script type="text/javascript">
    $().ready(function() {
        <% foreach (var m in Model.UserMessages) { %>
        $("#c<%=Html.AttributeEncode (m.ID) %>").click(function(event) {
            $.post("Home/CloseMessage/<%=Html.AttributeEncode (m.ID) %>");
            $("#m<%=Html.AttributeEncode (m.ID) %>").slideUp("slow");
            event.preventDefault();
        });
        <% } %>
    });
</script>

This is basically creating the javascript code in a C# loop which actually works but too much for me to digest. Is there any better way of doing this?

You could just create one javascript function that takes the element IDs as parameters :

function myFunction(ID) {
    $.post("Home/CloseMessage/" + ID);
    $("#m" + ID).slideUp("slow");
}

And :

<% foreach (var m in Model.UserMessages) { %>
<div class="um" id="m<%=Html.AttributeEncode(m.ID) %>">
    <p class="mh"><%= Html.Encode (String.Format ("From {0} ({1})", m.From, m.Sent)) %></p>
    <p><%= Html.Encode (m.Text) %></p>
    <% using (Html.BeginForm ("CloseMessage", "Home", new { id = m.ID })) { %>
        <input type="submit" value="Close<%= Html.AttributeEncode (m.ID) %>" 
        id="c<%= Html.AttributeEncode (m.ID) %>" 
        onclick="myFunction('<%=Html.AttributeEncode(m.ID)%>')"/>
    <% } %>
</div>
<% } %>

YOu could uses a CSS selector in your JS to get all buttons with a particular class assigned to them. Then you can wire up you click event to them. So your HTML would be something like this:

<% foreach (var m in Model.UserMessages) { %>
    <div class="um" id="m<%=Html.AttributeEncode(m.ID) %>">
        <p class="mh"><%= Html.Encode (String.Format ("From {0} ({1})", m.From, m.Sent)) %></p>
        <p><%= Html.Encode (m.Text) %></p>
        <% using (Html.BeginForm ("CloseMessage", "Home", new { id = m.ID })) { %>
            <input type="submit" class="MyCloseButton" value="Close<%= Html.AttributeEncode (m.ID) %>" id="c<%= Html.AttributeEncode (m.ID) %>"/>
        <% } %>
    </div>
<% } %>

I've only added the class="MyCloseButton" to your input

Then in your JS (I use mootools but JQuery has CSS selectors too but you will need to port it sorry) you can do something like this:

window.addEvent( "domready", function() {
  $$("input.MyCloseButton").each( function( button ) {
    // Add your code here, you can reference button.id etc for each of your buttons
  }
});

This way you only have to write out one little function in plan JS and not worry about doing it server-side, all you need to do it decorate your buttons with a css class so the JS can find them.

I understand its not pretty, but its not that bad either. I think there are easier ways to do this, however.

You can use jquery's positional selectors from the button's click event handler. Then just assign the same handler to every button.

<script type="text/javascript">
    $(document).ready(function() {        
        $("input[type=submit]").click(function(){
            $(this).parent().slideup("slow");
            $.post("Home/CloseMessage/" + $(this).parent().attr("id"));
            event.preventDefault();
          });
        });
    });
</script>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM