MVC #Url.Action not working - c#

<div class="col-xs-6 text-right margin-top-x5">
<div class="adduser pointer" data-url="#Url.Action("Register","Account")"><span class="glyphicons glyphicons-user"></span> Add New User</div>
</div>
On FireBug i can see but it not going to that action.
<div class="adduser pointer" data-url="/Account/Register">

If you want a div to be clickable, you have to give it some code to do something when the user clicks it.
$(function() {
$("[data-url]").click(function() {
location.href = $(this).data("url");
});
}
Alternatively, just use an anchor:
<a class="adduser pointer" href="#Url.Action("Register","Account")">
<span class="glyphicons glyphicons-user"></span> Add New User</a>

#Url.Action("Register","Account") is supposed to only print out the URL of the respective action at the specific place.
What you need instead is #Html.Action. Read more about it here

Are you possibly attempting to use an anchor?
<div class="col-xs-6 text-right margin-top-x5">
<a class="adduser pointer" href="#Url.Action("Register","Account")">
<span class="glyphicons glyphicons-user"></span> Add New User</div>
Or you could use a Html.ActionLink
<div class="col-xs-6 text-right margin-top-x5">
<span class="glyphicons glyphicons-user" />
#Html.ActionLink("Add New User", "Register", "Account", null, new { #class = "adduser pointer" })

Related

TagBuilder not generating unqiue id attribute values across ajax requests

I have an issue where I'm using the same template to render some content on a page and the same template is used to render additional content on the page using an AJAX request.
The following code renders the partial razor view:
#model SearchBoxViewModel
<div class="smart-search">
#using (Html.BeginForm("Index", "Search", FormMethod.Get, new { #class = "form-horizontal", role = "form" }))
{
<div class="form-group">
<div class="hidden-xs col-sm-1 col-md-1 col-lg-1 text-right">
#Html.LabelFor(m => m.SearchPhrase, new { #class = "control-label heading" })
</div>
<div class="col-xs-8 col-md-9 col-lg-10">
#Html.TextBoxFor(m => m.SearchPhrase, new {#class = "form-control", placeholder = "for products, companies, or therapy areas"})
</div>
<div class="col-xs-4 col-sm-3 col-md-2 col-lg-1">
<input type="submit" value="Search" class="btn btn-default"/>
</div>
<div class="what-to-search hidden-11 col-sm-11 col-sm-offset-1">
<div class="checkbox">
<label>
#Html.CheckBoxFor(m => m.WhatToSearch, null, false)
#Html.DisplayNameFor(m => m.WhatToSearch)
</label>
</div>
</div>
</div>
}
</div> <!-- /.smart-search -->
The following code makes the AJAX request:
$.ajax(anchor.attr("data-overlay-url-action"))
.done(function (data) {
$("div.overlay").addClass("old-overlay");
$("div.navbar").after(data);
$("div.overlay:not(.old-overlay)")
.attr("data-overlay-url-action", anchor.attr("data-overlay-url-action"))
.hide()
.fadeIn();
$("div.old-overlay")
.fadeOut()
.removeClass("old-overlay");
anchor.addClass("overlay-exists");
});
So what you get is the same partial razor view output on the page twice, once during the page request and once during the AJAX request.
The problem is that TextBoxFor, CheckBoxFor, etc. all make use of TagBuilder.GenerateId to generate the id attribute value but it doesn't account for generating id's across multiple requests where AJAX might be involved. This results in the same id value being output on the page, causing JavaScript to break.
The following is the HTML that is output twice (once during the request and then added in a separate part of the page during an AJAX request):
<div class="smart-search">
<form role="form" method="get" class="form-horizontal" action="/PharmaDotnet/ux/WebReport/Search"> <div class="form-group">
<div class="hidden-xs col-sm-1 col-md-1 col-lg-1 text-right">
<label for="SearchPhrase" class="control-label heading">Search</label>
</div>
<div class="col-xs-8 col-md-9 col-lg-10">
<input type="text" value="" placeholder="for products, companies, or therapy areas" name="SearchPhrase" id="SearchPhrase" class="form-control">
</div>
<div class="col-xs-4 col-sm-3 col-md-2 col-lg-1">
<input type="submit" class="btn btn-default" value="Search">
</div>
<div class="what-to-search hidden-11 col-sm-11 col-sm-offset-1">
<div class="checkbox">
<label>
<input type="checkbox" value="true" name="WhatToSearch" id="WhatToSearch">
NewsManager Search Only
</label>
</div>
</div>
</div>
</form></div>
So the SearchPhrase and WhatToSearch id's are duplicated.
Is there any way to work around this, or is there a better way to render the form elements to avoid this issue?
You could specify your own ID for the items, and then you wouldn't have this ID collision problem. Have you tried setting the id manually: Html.TextBoxFor( ... , new { id = "AnythingHere" }), where the id could be a freshly generated Guid? (Note that you'd probably need to add a prefix, because Guids can start with a number.
So you can use the following. The Guid doesn't look good, and is unnecessarily long. You might want to go with something shorter, like short guid, DateTime.Ticks, ...
#{
var id = "chk_" + Guid.NewGuid().ToString();
}
#Html.CheckBoxFor(..., new { id = id })
#Html.LabelFor(..., new { #for = id })

MVC multiple different submit buttons? what is the best approach?

UPDATE:
Here is my .html page looks like and withing the form tag I have couple of buttons (page size, save to db, remote items)
<div class="col-lg-12">
<div class="panel panel-info">
<div class="panel-heading">
<h3 class="panel-title">Records</h3>
</div>
#using (Html.BeginForm("Index", "MyController", FormMethod.Post, new { #id = "form_header" }))
{
<div class="panel-body">
<div class="row">
<div class="col-xs-4">
<div class="form-group">
<label for="" class="col-xs-5 control-label">Rows per page:</label>
<div class="col-xs-4">
#Html.DropDownListFor(m => m.PageSize,
new List<SelectListItem>
{
new SelectListItem() { Text = "10", Value = "10" },
new SelectListItem() { Text = "25", Value = "25" },
new SelectListItem() { Text = "50", Value = "50" },
new SelectListItem() { Text = "ALL", Value = "ALL" }
}, new { #class = "form-control", Name = "pageSizeDDL" })
</div>
</div>
</div>
<div class="row text-right">
<div class="col-xs-12">
<button class="btn btn-success" type="submit" id="btnSavetoDB" name="saveToDB" value="Save to DB">
<span> <i class="fa fa-save"></i> Save to Database </span>
</button>
<button class="btn btn-danger" type="submit" id="btnRemoveFromGrid" name="removeItems" value="Remove Item From Grid">
<span> <i class="fa fa-remove"></i> Remove </span>
</button>
</div>
</div>
</div>
<div class="col-lg-14">
<div class="panel-body">
<div class="row">
<div class="test" style="overflow: scroll; width: 100%">
<div style="width: 1000px">
#if (Model != null)
{
//grid
}
</div>
</div>
</div>
</div>
</div>
</div>
}
</div>
I have seen all sorts of approach but still not convinced the best way to handle and in my situation I have multiple buttons or events that fire based on the user action: for an example in my case:
in the form:
I have page size dropdown where user can select number of rows to display
I have a import button to import the doc
I have save button - save to db
I have a remove button - remove from grid
currently this is how I have laid out:
[HttpPost]
public ActionResult Index(HttpPostedFileBase file, FormCollection formCollection, string pageSizeDDL, string saveToDB, string removeItems, string PageList)
{
if (file upload) {....}
if (formCollection) { .... }
if (pageSizeDDl {....}
..........
}
my question is:
What if i need the form values for all buttons or perhaps is that right approach the way I'm doing?
I have seen wrapping each button in it's own form in view which I things its not the correct approach and the reason is if I have 10 button in a single page does it mean I have to have 10 form?

Div inside a href with ActionLink

I have to integrate a design that includes this kind of menu item:
<div class="cell first">
<a href="#">
<div id="m_account" class="img"></div>
<div class="menu_item">my account</div>
</a>
</div>
How can I make an ActionLink to provide this kind of code?
I sometimes use areas so some links must have new {area = "MyAccount"} attribute.
Thanks.
You can do this:
<div class="cell first">
<a href="#url.Action("YourAction")">
<div id="m_account" class="img"></div>
<div class="menu_item">my account</div>
</a>
</div>
There is no link in this HTML that an ActionLink can replace :
<div class="cell first">
<a href="#">
<div id="m_account" class="img"></div>
<div class="menu_item">my account</div>
</a>
</div>
if you wanted to do something like this:
<a href="myAccount/Login" class="img" id="m_account"/></a>
that would be written like:
#Html.ActionLink("ActionName", "ControllerName", new { id = "m_account", #class = "img" })
you just put any attribute name and values in the second part of the ActionLink
Instead of using Html.ActionLink, use Url.Action
<div class="cell first">
<a href="#(Url.Action("ActionName", "ControllerName"))">
<div id="m_account" class="img"></div>
<div class="menu_item">my account</div>
</a>
</div>

ASP MVC Submit button not doing anything. At all

I have a (simple) ASP MVC view:
<div class="row">
<div id="dashboard-left" class="col-md-8">
#using (Html.BeginForm("ConfigureOffers", "Offers", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<div style="padding-bottom: 10px;">
<p style="font-size: large;"><strong>Available</strong></p>
</div>
<div class="accordion" id="accordion2">
<div class="widget" style="background:#fff !important">
#{
int i = 0;
}
#foreach (var prod in Model.allProducts)
{
<div class="accordion-group">
<div class="accordion-heading">
<a class="accordion-toggle" data-toggle="collapse" data-parent="accordion2" href="#collapse#(i)">
<h4 class="widgettitle" id="QuickTitle">> #prod.Description_VC</h4>
</a>
</div>
<div id="collapse#(i)" class="accordion-body collapse" style="height: 0px;">
<div class="accordion-inner" style="margin-left: 10px;">
<div style="padding-bottom: 10px;"><strong>Total product:</strong> #{
for (int k = 0; k < Model.OfferHeaders.Count(); k++)
{
if (Model.OfferHeaders[k].Product_ID == prod.Product_ID)
{
#Html.TextBoxFor(o => o.OfferHeaders[k].Amount_DEC);
break;
}
}
}
</div> #*prod div*#
</div> #*accordion-inner*#
#{i++;}
</div>
<div style="clear:both;"></div>
</div>
}
<input type="submit" class="btn btn-default" value="Save Changes" />
</div> #*widget*#
</div> #*accordion*#
}
</div>
<!-- col-md-4 -->
</div>
<!--row-->
The basis of this view was taken from another (working page), but for some reason, clicking the submit button doesn't trigger the server action detailed in the BeginForm element. I get no errors from Visual Studio, nor any JavaScript errors from the browser console, and nothing seems to happen server-side.
One possible reason for Action not happening is mainly when you put
the action in the View and also created the page. but i think you
have forgot mentioning the ActionResult in the controller.
Another possible option is you have to use [HttpPost] above your
method in controller where you specified the ActionResult
[HttpPost]
public ActionResult ConfigureOffers(ModelClass instance)
{
...
}
Other possible reasons
The routes are not correct
The Form Action property is not correct
You are using nested FORM tags

Add onsubmit event to call JS function in MVC3

I have a problem with calling JS method from form in MVC3 project: I have a "search"page without forms with two buttons - Search and Cancel. Click on search runs JS function runSearch in ProductDefinition.
<div id="productSearch-dialog" class="modal fade" style="width: 1000px; display: none">
<div class="modal-header">
<button class="close" aria-hidden="true" data-dismiss="modal" type="button">×</button>
<h3>Search Results</h3>
</div>
<div class="modal-body" style="height: 650px;">
<div>
<input id="inputname" type="text" /><font class="red-font" id="lblrequired" style="display: none">*</font>
</div>
<div id="searchresultcontain" class="grid">
</div>
<div id="Pagination" class="pagination">
</div>
</div>
<div class="modal-footer">
<button class="btn btn-primary" onclick="productDefinition.runSearch();">Search</button>
<button class="btn btn-primary" data-dismiss="modal">Cancel</button>
</div>
How can I run this JS method (runSearch) when I press ? As far as I understand, this will be onsubmit event which is form event, so I am need to add form element with onsubmit property. I tried surrounding input field with BeginForm helper method:
#using (Html.BeginForm(new { onsubmit = "productDefinition.runSearch();" }))
{
<input id="inputname" type="text" /><font class="red-font" id="lblrequired" style="display: none">*</font>
<input type="submit" value="Submit" style="visibility: hidden" />
}
but it does not seem to be working - when I press enter I for some reason get source of the page and arrive at localhost/?onsubmit=productDefinition.runSearch() URL.
What can be the source of the problem and how can I get the same behaviour for onsubmit as for onclick?
#using (Html.BeginForm(new { onsubmit = "return runSearch();" }))
<script type="text/javascript">
function runSearch() {
// your logic to perform the search.
return true;
}
</script>
You need to use the following version of BeginForm method in order to specify html attributes.
However, it is considered a bad practice to use inline javascript so I would suggest to assign and id attribute to your form and handle its submit event in the external javascript file instead. If you are using jQuery for your project, here is a good example from their docs - http://api.jquery.com/submit/. In plan JavaSCript it is a bit more tricky but still easy to do.
#model Models.Person
<script type="text/javascript">
$(document).ready(function () {
$('#registerInputId').click(function () {
alert('what do you do before send? For example encrypt the password');
$('#Password').val(CryptoJS.MD5($('#Password').val()));
})
});
</script>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal" style="display: inline-block; margin: 5% auto;">
<div style="font-size: 18px; margin-right:2px; margin-bottom:20px; text-align:right;">Add form</div>
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-5" })
<div class="col-md-7">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Password, htmlAttributes: new { #class = "control-label col-md-5" })
<div class="col-md-7">
#Html.EditorFor(model => model.Password)
#Html.ValidationMessageFor(model => model.Password)
</div>
</div>
<div class="form-group" style="margin-top: 30px;">
<div class="col-md-offset-3 col-md-6">
<input id="registerInputId" type="submit" value="Register" class="btn btn-default" />
</div>
</div>
</div>
}
Form.Id is required if onsubmit handler implements generic functionality, applicable for multiple forms. (example : disabling all input fields)
Form
#using (Html.BeginForm(new {
id = "form24",
onsubmit = "return onSubmitHandler(id);"
}))
handler
<script type="text/javascript">
function onSubmitHandler(formId) { /*formId is form24 */ }
</script>

Categories