how to insert content to Ajax.ActionLink - asp.net

In Asp.net mvc3 razor I have:
Ajax.ActionLink("Hello world", "Hello", "Say", new RouteValueDictionary(new { word = "Hello" }),new AjaxOptions { HttpMethod = "GET", InsertionMode = InsertionMode.Replace, UpdateTargetId = "dynamic-container" })
it produces
<a href="...." ...>Hello world</a>
What I would like to get is
<a href="..." ...><my><html><content/></html></my></a>
How can I pass "" so that it will be inserted instead of the standard text?

I've just found a solution
http://forums.asp.net/post/4517653.aspx
It's not as elegant as I would expected but should do.
Anyone has a better idea?

the code:
Ajax.ActionLink("Hello world", "Hello", "Say", new RouteValueDictionary(new { word = "Hello" }),new AjaxOptions { HttpMethod = "GET", InsertionMode = InsertionMode.Replace, UpdateTargetId = "dynamic-container" })
with the link provided results in a error. The link looks like this:
.../Say/Hello?Count=1&Keys=System.Collections.Generic.Dictionary%602%2BKeyCollection%5BSystem.String%2CSystem.Object%5D&Values=System.Collections.Generic.Dictionary%602%2BValueCollection%5BSystem.String%2CSystem.Object%5D
which is BAAADDDDD.... the issue is that this uses the wrong overload. Instead of:
new RouteValueDictionary(new { word = "Hello" })
where should be:
new { word = "Hello" }
when the code form the link in a previous answer works like a charm - hope it'll be helpful for somebody, anybody

You can use javascript / jQuery to force an insert into the item after rendering. This may be a bit 'quick and dirty' but it does get the job done without too much effort.
Attach a class using the HtmlAttributes object for each #Ajax.Action to allow you to select them later using JS:
#Ajax.ActionLink(..... new { #class = "AjaxLink btn btn-primary" })
Then use javascript / jQuery to find the link(s) by class, and replace the innerHTML of each. The following is a jQuery example, it could also be written in plain javascript. I personally like the jQuery was as it's more concise:
<script type="text/javascript">
//hack to insert a <span> inside the remove links so that the text can be styled
$('.AjaxLink ).html('<i class="fa fa-minus-circle"></i><span class="ActionLinkText">Your Text here</span>');
</script>
Hope this helps

The solution #4rchie pointing of using helper method is the best solution. But there is another way which keeps the data to be inserted with the link using a data-* attribute and use jquery to do rest of the work.
For example:
<div class="list-group">
#foreach (var item in Model.Things)
{
#Ajax.ActionLink(item.Name, "actionName", "controllerName", new { Id = item.Id }, new AjaxOptions { HttpMethod = "GET", InsertionMode = InsertionMode.Replace, UpdateTargetId = "areaPanel", OnComplete = "" }, new { #class = "list-group-item", data_frequency = item.frequency})
}
</div>
Jquery code:
jQuery(document).ready(function () {
$("[data-frequency]").each(function () {
var linkText = $(this).html();
var attr = $(this).attr("data-frequency");
$(this).html("<span class ='badge'>" + attr + "</span>" + linkText);
})
}
The result is like http://getbootstrap.com/components/#list-group-badges

Related

Razors Html Helpers

How do you make a Razors helper "Dropdownlist" or what arguments would have to pass to make it editable. For example if I want to scroll down it should let me or if I want type Instead it should let aswell.
#Html.DropDownList("CustomerId", null, htmlAttributes: new { #class = "form-control" } )
Also, if you I choose to use twitter-typeahead with EF razors how do use the "Editfor" so that once the user click on the right item, it sends the ID of that item to the database. In-other words, how do use a navigation property with razors "Editfor" helper.
#Html.EditorFor(model => model.CustomerId, null, "customer",new {htmlAttributes = new { #class = "form-control" } })
I will try to help you convert the basic example of the following page to a razor page equivalent.
http://twitter.github.io/typeahead.js/examples/
You must know that this jquery plugin displays just a list of strings and the user will select one of the values and then you will have to find the id using C# code. I will just show you how to implement the twitter typehead using razor pages but you will have to make some extra work in order to get the id.
First of all you will need the html part
<div id="the-basics">
<input class="typeahead" type="text" placeholder="States of USA">
</div>
Next you need to declare your list using C#.
List<string> Values = new List<string> { "Value 1", "Value 2", "Value 3" };
Now you will have the following HTML.
var substringMatcher = function(strs) {
return function findMatches(q, cb) {
var matches, substringRegex;
// an array that will be populated with substring matches
matches = [];
// regex used to determine if a string contains the substring `q`
substrRegex = new RegExp(q, 'i');
// iterate through the pool of strings and for any string that
// contains the substring `q`, add it to the `matches` array
$.each(strs, function(i, str) {
if (substrRegex.test(str)) {
matches.push(str);
}
});
cb(matches);
};
};
var states = #Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Values));
$('#the-basics .typeahead').typeahead({
hint: true,
highlight: true,
minLength: 1
},
{
name: 'states',
source: substringMatcher(states)
});
I hope it helps.

Ajax.BeginForm is not working as expected

I have a very strange problem with Aajx.BeginForm. I have this code :
In view :
#using (Ajax.BeginForm("Upload", "Profile", new AjaxOptions() { HttpMethod = "POST" }, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<input type="file" name="files"><br>
<input type="submit" value="Upload File to Server">
}
In controller :
[HttpPost]
[ValidateAntiForgeryToken]
public void Upload(IEnumerable<HttpPostedFileBase> files)
{
if (files != null)
{
foreach (var file in files)
{
// Verify that the user selected a file
if (file != null && file.ContentLength > 0)
{
// extract only the fielname
var fileName = Path.GetFileName(file.FileName);
// TODO: need to define destination
var path = Path.Combine(Server.MapPath("~/Upload"), fileName);
file.SaveAs(path);
}
}
}
}
The problem is that I get null file when the form is submit. I read many question that is the same of my question, but most of the answers was that the name of input type="file" is not as the same name of the parameter name in the controller. I found some examples, I try this one which is almost the same of my code except for the jquery files, so I tried to replace the jquery files with these files :
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7/jquery.js"></script>
<script src="http://malsup.github.com/jquery.form.js"></script>
And here is the surprise !!. When the form is submit, I get the file but the form is post back. It is work as there is no ajax. I search in google for Ajax.BeginFrom that is post back and found many solutions in stackoverflow and most of of the answers was that jquery.unobtrusive-ajax file must be included in the page. It like a circle of problems, once you solve one you get another. Does I miss something ?
You cannot submit files with Ajax.BeginForm(). The helper uses the jquery.unobtrusive-ajax.js file to submit the data using ajax functions which do not allow multipart/form-data enctype.
One option is to use FormData (but not supported in older browsers). Change the Ajax.BeginForm() to Html.BeginForm() and then handle the forms submit event
$('form').submit(function() {
var formdata = new FormData($('form').get(0));
$.ajax({
url: '#Url.Action("YourActionName", "YourControllerName")',
type: 'POST',
data: formdata,
processData: false,
contentType: false,
success: function() {
.... // do something?
}
});
});
In addition there are numerous jquery plugins that you can use for uploading files (14 of them are listed here)
Side note: Your file input allows selection of only one file, so your method parameter should be HttpPostedFileBase files (not IEnumerable<HttpPostedFileBase> files) or alternatively, include the multiple attribute in the file input.
You need to specify the encoding type in your form.
#using (Ajax.BeginForm("Upload", "ControllerName", new AjaxOptions { HttpMethod = "POST"}, new { enctype = "multipart/form-data"}))
{
#Html.AntiForgeryToken()
<input type="file" name="files"><br>
<input type="submit" value="Upload File to Server">
}

Applying css on ActionLink in mvc?

I am working in mvc5. I made a simple action link in a view using this syntax
#Html.ActionLink("Manage List", "Index", new { #class = "ManageLink" });
But css was not working untill i added controller name like this:
#Html.ActionLink("Manage List", "Index",new { controller = "ControllerName" }, new { #class = "ManageLink" });
I want to know why we need to define controller name here while it is quite obvious that every view is related to some action method of a controller ? I am very new to mvc so need to know these kind of things.
Thanks for the help.
You could also have fixed this by simply specifying the name of the optional parameter you wanted to set:
#Html.ActionLink("Manage List", "Index", htmlAttributes: new { #class = "ManageLink" });
Otherwise, the Razor engine has to try to figure out which overload of the ActionLink method you're trying to call; sounds like in your case it thought the third argument was for the routeValues parameter.
This would also work:
#Html.ActionLink("Manage List", "Index", "ControllerNameHere", new { #class = "ManageLink" });

jquery adding an onclick event to a href link

i am converting over from websforms to asp.net mvc and i have a question.
i have a loop that generates links dynamicallly where picNumberLink is a variable in a loop and image is a variable image link.
i want to avoid putting javascript actions inline so in my webforms project is did the following:
hyperLink.Attributes.Add("onclick", "javascript:void(viewer.show(" + picNumberlink + "))");
what is the equivalent using jquery in asp.net mvc?
I have seen examples of using the $(document).ready event to attach on clicks but i can't figure out the syntax to pass in the picNumberLink variable into the javascript function.
suggestions?
EDIT: If you generate your links with the ID of this form:
<a id="piclink_1" class="picLinks">...</a>
<a id="picLink_2" class="picLinks">...</a>
<script type="text/javascript">
$('a.picLinks').click(function () {
//split at the '_' and take the second offset
var picNumber = $(this).attr('id').split('_')[1];
viewer.show(picNumber);
});
</script>
var functionIWantToCall = function(){
var wrappedLink = $(this);
//some serious action
}
//this should be called on document ready
$("#myLinkId").click(functionIWantToCall);
If you need to get URL of picture, keep it in anchor`s href:
var functionIWantToCall = function(event){
event.preventDefault(); //this one is important
var link = $(this).attr('href');
//some serious action
}
$(document).ready(function()
{
$('#LinkID').click(function() {
viewer.show($(this).attr('picNumber'));
});
});
You can add an attribute called picNumber to your hyperlink tag and set this is your mvc view
The link in your view might look something like this:
<%= Html.ActionLink("Index", new { id = "LINKID", picNumber = 1 }) %>
Assuming you're able to change the HTML you output, can't you put the picNumberLink in the id or class attribute?
HTML:
<img src="..."/>
jQuery:
$(function() {
// using the id attribute:
$('.view').click(function() {
viewer.show(+/-(\d+)/.exec(this.id)[1]);
});
// or using the class attribute:
$('.view').click(function() {
viewer.show(+/(^|\s)foo-(\d+)(\s|$)/.exec(this.className)[2]);
});
}}

JQuery refactoring help needed

Here's my javascript code:
<script type="text/javascript">
$(document).ready(function() {
var currentInput = '';
var currentLabel = '';
$("#userLookup").click(function() {
var url = "<%= Url.Action( "ListAll" , "User") %>";
currentInput = $("#User");
currentLabel = $("#lblUser");
openModal(url);
return false;
});
$("#locationLookup").click(function() {
var url = "<%= Url.Action( "ListAll" , "Location") %>";
currentInput = $("#Location");
currentLabel = $("#lblLocation");
openModal(url);
return false;
});
$(".selectable").live("click", function(e){
currentInput.val($(this).attr('id'));
var labelText = $(this).parent().parent().find('td').eq(2).html();
currentLabel.html(labelText);
$.fn.colorbox.close();
e.preventDefault();
});
});
function openModal(url){
$.fn.colorbox({
href:url
, open:true
, width: "400px"
, height: "300px"
});
}
</script>
And here's my HTML
<table width = "100%">
<tr>
<td>Asset User Id:</td>
<td><%= Html.TextBox("User", Model.User, (object)new{style = "width:100px", maxLength="20"})%>
<a id="userLookup" href="#">Lookup User</a>
<label id="lblUser"></label>
<%=Html.ValidationMessage("User")%></td>
</tr>
<tr>
<td>Location Id:</td>
<td><%= Html.TextBox("Location", Model.Location, (object)new{style = "width:100px", maxLength="20"})%>
<a id="locationLookup" href="#">Lookup Location</a>
<label id="lblLocation"></label>
<%=Html.ValidationMessage("Location")%></td>
</tr>
</table>
I have plenty of more lookup fields (which i omitted) similar to the two listed above and i was looking to see if anyone could help me come up with a cleaner/dry method of doing something like this?
Thanks
I would add the url for the modal box into the link itself. Then you could just add a class to that link to invoke the required functionality. It also means that you can have your JS in an external file and your JS doesn't have a dependence on the ASP.NET MVC Html helper methods.
Change your html to something like:
<table width = "100%">
<tr>
<td>Asset User Id:</td>
<td>
<%= Html.TextBox("User", Model.User, (object)new{style = "width:100px", maxLength="20"})%>
<%= ActionLink("Lookup User", "ListAll", "User", null, new { class="lookup-link" }) %>
<label id="lblUser"></label>
<%=Html.ValidationMessage("User")%>
</td>
</tr>
<tr>
<td>Location Id:</td>
<td>
<%= Html.TextBox("Location", Model.Location, (object)new{style = "width:100px", maxLength="20"})%>
<%= ActionLink("Lookup Location", "ListAll", "Location", null, new { class="lookup-link" }) %>
<label id="lblLocation"></label>
<%=Html.ValidationMessage("Location")%>
</td>
</tr>
</table>
Then you can simplify your jQuery to something like:
var currentInput = '';
var currentLabel = '';
$(".lookup-link").click(function() {
var url = $(this).attr("href");
currentInput = $(this).siblings("input")[0];
currentLabel = $(this).siblings("label")[0];
openModal(url);
return false;
});
I haven't tested any of this code, so there's probably a million errors. ;-)
HTHs,
Charles
You could have a sort of jquery plugin that attaches the click handlers for userLookup and locationLookup. It would probably take 3 arguments:
url
input
label
otherwise, you could have a function that takes 4 (the first being the item to bind the click handler to) and runs the exact code you have above.
Just don't go over the top. If you start adding more arguments for one-off solutions (e.g. boolean whether to show modal with "x" or "close" at the top), then probably you're just complicating things.
If you use a convention for naming all of your lookup elements you could create a general funciton that would work for all instances.
Something like:
OpenLookupModal(lookupId)
{
var inputName = lookupId.id.substr(0, lookupId.id.indexOf('Lookup'); //take all of the id before the word "lookup"
var currentInput = $("#" + inputName ));
var currentLabel = $("#lbl" + inputName);
openModal(url);
return false;
}
To use it:
$("#locationLookup").click(OpenLookupModal("#locationLookup"));
You could even get fancy and bind the click event of all id's ending in "Lookup" in one statement:
$("[id$='lookup']").click(OpenLookupModal(this));
Warning: This code is untested, but hopefully it gets the idea across.

Resources