Ajax.ActionLink not working with htmlAttributes - asp.net

I have ajax.actionlink in my view defined as:
#Ajax.ActionLink(item.sifra_pozicije, //link text
"UnosuProjekat", // action name
"Projekti", // controller
new { poz = item.sifra_pozicije.ToString(), proj = "Projekat 1" }, // route values
new AjaxOptions() { UpdateTargetId = "Projekat" }, // ajax options
new { #class = "openDialog" } //htmlAttributes
)
and generating HTML code
VSG010002
This is sending empty strings to controller action with url request
http://localhost:64908/Projekti/UnosuProjekat?_=1397501602503
When i remove htmlAttributes from link, HTML stays the same (except class is removed) and parameters are passed to controller.
Can someone tell me what's wrong with this?

Related

Unable to add HTML.BeginForm inside ASP.NET WebGrid

I have the following code inside my asp.net MVC-4 razor view:-
gridcolumns.Add(new WebGridColumn()
{
CanSort = false,
Format =
(item) =>
{
var banner = item.Value as Sales.Models.DeleteAllRequest;
if (!banner.Approved)
{
return Html.ActionLink("Approve", "DeleteRequestDeleteAll", "Customer", new { customerid = banner.CustomerID, requestid = banner.ID },
new AjaxOptions
{
Confirm = "Are You sure You want to delete (" + banner.CustomerName.ToString() + ")",
OnSuccess = "deletionconfirmation",
OnFailure = "deletionerror"
});
}
return "";
}
});
The above code will add <a> link inside the ASP.NET web grid column. but since i am doing a Delete action so i should be sending Post request instead of Get request. so i am not sure how i can use Html.BeginForm instead of Html.ActionLink inside my above code?
Thanks

Asp.net MVC Ajax Button to retrieve a single data

I want to retrieve the first record in my database when ever I click the Ajax button, right now whenever I click my button it returns a List of my Record, I just want to retrieve the first record then when I click it again, returns the second record, is that even possible?
Here is my Ajax button :
#Ajax.ActionLink(" ", "BtnNext", null#*new { count = count + 1}*#, new AjaxOptions
{
HttpMethod = "GET",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "current"
}, new { #class = "Middle-next dim btn btn-large-dim", #id = "Link1"})
Here is the controller for the Ajax button :
public PartialViewResult BtnNext()
{
var model = db.Queues.OrderBy(x => x.QueueNumber);
return PartialView("_queuenumber", model);
}
Thankyou so much, newbie <<
Try this
var model = db.Queues.ToList().OrderBy(x => x.QueueNumber).Take(1);

How to use MapRoute, using ActionLink()?

I have this route values inside Global.asax
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
"Edit", // Route name
"Admin/{controller}/{action}/{id}", // URL with parameters
new { controller = "Edit", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
and I use this ActionLink method to call the Edit route
#Html.ActionLink("Edit", "Topic", "Edit", new { id = item.ID })
Now the result of the link generated is like this...
http://localhost:777/Admin/Topic?Length=4
How to use the route and target properly using the ActionLink method.
Thanks!
Use the correct overload of ActionLink to get the intended result
#Html.ActionLink("Edit", "Topic", "Edit", new { id = item.ID }, null)
The overload is ActionLink(string linkText, string actionName, string controllerName, object routeValues, object htmlAttributes)
Adding the null as null HTML attributes is necessary when you supply parameters to the action. Or if you actually needed to apply HTML Attributes to the link, you would use:
#Html.ActionLink("Edit", "Topic", "Edit", new { id = item.ID }, new { #class = "MyCustomCssClassName" } )

How to populate ExtJS Tree with data from Spring MVC Controller?

As a newbie in ExtJS I'm trying to use it with Spring MVC Controller. So my structure is following: tree.jsp gets JSON data from SomeController.java. I'm using Tiles 2 to connect them.
tree.jsp
<script type="text/javascript">
if (Ext.BLANK_IMAGE_URL.substr(0,5) != 'data'){
Ext.BLANK_IMAGE_URL = '/ext-3.3.1/resources/images/default/s.gif';
}
Ext.onReady(function(){
var proxy = new Ext.data.HttpProxy({
api: {
read: 'jsonTree'
}
});
var treeLoader = new Ext.tree.TreeLoader({
proxy: proxy
});
// shorthand
var Tree = Ext.tree;
var tree = new Tree.TreePanel({
el:'tree-div', //we need to have a div in our html named this
title: "Data Sources",
useArrows:true,
autoScroll:true,
animate:true,
enableDD:true,
containerScroll: true,
rootVisible: false,
loader: treeLoader,
root: {
nodeType: 'async',
text: 'Ext JS',
draggable:false,
id:'source'
}
});
// render the tree
tree.render();
});
SomeController.java
#Controller
#RequestMapping("/some")
public class SomeController {
private Logger log = LoggerFactory.getLogger(CountryReferenceBookController.class);
private static final String LIST_VIEW_KEY = "redirect:list.html";
#Autowired
private RestTemplate restTemplate;
#RequestMapping(value = "/jsonTree/{languageId:\\d+}")
public #ResponseBody Map<String, ? extends Object> getJsonTreeInfo(#PathVariable("languageId") Long languageId) {
List treeList = new ArrayList<Map<String, Object>>();
List<ReferenceBookTitleImpl> list = new ArrayList<ReferenceBookTitleImpl>();
list = restTemplate.getForObject("http://localhost:8084/xcollector/restService/reference/list", list.getClass());
for (ReferenceBookTitleImpl title : list) {
String description = restTemplate.getForObject("http://localhost:8084/xcollector/restService/reference/title/" + title.getId() + "/content/" + languageId, String.class);
//create a child node that is a leaf
Map child = new HashMap();
child.put("id", title.getId());
child.put("text", description);
child.put("checked", Boolean.FALSE);
child.put("leaf", Boolean.TRUE);
treeList.add(child);
}
//the spring mvc framework takes a hashmap as the model..... :| so in order to get the json array to the View, we need to put it in a HashMap
Map modelMap = new HashMap();
modelMap.put("JSON_OBJECT", treeList);
log.info("jsonArray: " + treeList.toString());
return modelMap;
}
}
When I send a GET response to the controller I get a file with json array instead of the populated tree. What is wrong with my code?
Thanks a lot in advance,
L.
Since nobody had asked I decided to answer my question myself. The main problem was wrong understanding of AJAX call.
If you want to populate a tree panel from Spring MVC Controller you have to implement two methods: the first returns a view where the tree panel is located, the second returns a data which the tree panel is populated with.
Let's take a look at the example:
First of all, I use Tiles 2 in the project. So in a file with tiles (templates.xml) I added a following tile:
<definition name="/tree" extends="defaultTemplate">
<put-attribute name="title" value="Tree" />
<put-attribute name="content" value="/WEB-INF/jsp/tree.jsp"/>
</definition>
The Controller which on charge of processing requests on an url http://<ip:port>/<web-app>/tree has two methods:
This method returns jsp view:
#RequestMapping(value = "/tree")
public ModelAndView getTreeView() {
return new ModelAndView("/tree");
}
Next method returns json data:
#RequestMapping(value = "/tree/data", method=RequestMethod.POST)
public #ResponseBody List<Map<String, Object>> getJsonTreeInfo() {
List treeList = new ArrayList<Map<String, Object>>();
List<FooImpl> list = new ArrayList<FooImpl>();
list = restTemplate.getForObject("http://localhost:8084/<web-app>/restService/list", list.getClass());
for (FooImpl foo : list) {
String description = restTemplate.getForObject("http://localhost:8084/<web-app>/restService/title/" + foo.getId() + "/content/11", String.class);
//create a child node that is a leaf
Map child = new HashMap();
child.put("id", foo.getId());
child.put("text", description);
child.put("leaf", Boolean.TRUE);
treeList.add(child);
}
return treeList;
}
Could be unclear how this list becomes json array. I have a message converter which is doing all the job of converting.
JSP side:
<script type="text/javascript">
if (Ext.BLANK_IMAGE_URL.substr(0,5) != 'data'){
Ext.BLANK_IMAGE_URL = '/ext-3.3.1/resources/images/default/s.gif';
}
// application main entry point
Ext.onReady(function() {
// shorthand
var Tree = Ext.tree;
var tree = new Tree.TreePanel({
useArrows: true,
autoScroll: true,
animate: true,
enableDD: true,
containerScroll: true,
border: false,
// auto create TreeLoader
dataUrl: 'tree/data',
root: {
nodeType: 'async',
text: 'List',
draggable: false,
id: 'src'
}
});
// render the tree
tree.render('tree-div');
tree.getRootNode().expand();
});
</script>
<div id="tree-div"></div>
This line dataUrl: 'tree/data' sends POST request to the second contoller's method. It returns the json array. Finally, the tree is popullated with data :) Everyone is happy :)
I hope it helps someone because I spent a lot of time to come to this solution.
Enjoy your job :)

How do you override route table default values using Html.ActionLink?

Global.asax route values
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional, filterDate = DateTime.Now.AddDays(-1), filterLevel = "INFO" } // Parameter defaults
);
Here's my actionlink
#Html.ActionLink(item.MachineName, "Machine", new { id = item.MachineName, filterLevel = "hello" }, null)
When the filterlevel is specified in the actionlink, it generates a url like this:
http://localhost:1781/LoggingDashboard/log/level/VERBOSE
Which is the same page as I am currently on. If I change the actionlink to use a property other than one that has a default value in the route table (yes, if I use filterDate it messes up too), it generates a link like this:
#Html.ActionLink(item.MachineName, "Machine", new { id = item.MachineName, foo = "bar" }, null)
http://localhost:1781/LoggingDashboard/log/Machine/C0UPSMON1?foo=bar
Is this behavior correct? Should I not be able to override the defaults set up in the route table? I have confirmed that if I remove the filterLevel default from the route table this works as I expect:
http://localhost:1781/LoggingDashboard/log/Machine/C0UPSMON1?filterLevel=VERBOSE
---EDIT---
sorry, here is the action
public ActionResult Machine(string id, DateTime filterDate, string filterLevel)
{
...
var model = new LogListViewModel { LogEntries = logEntries };
return View(model);
}
For the bounty I want to know how to override the "default" values that are specified in the routes from global.asax. i.e. I want to be able to override filterLevel and filterDate.
SLaks already said what is probably the best way to handle this problem. I don't know if this will work, but, what happens if you put this above the existing route (so there would be two in your global.asax now)?
routes.MapRoute(
"Filtered",
"{controller}/{action}/{id}?filterLevel={filterLevel}&filterDate={filterDate}",
new
{
controller = "Home",
action = "Index",
id = UrlParameter.Optional,
filterDate = DateTime.Now.AddDays(-1),
filterLevel = "INFO"
}
);
Also, it just occurred to me that the reason you don't like SLaks' solution is that it could be repetitive. Since you only have one route, these parameters probably indicate a global functionality, instead of an action-scoped functionality. You could fix this by adding the values in an action filter on each controller, or your could use a custom route handler to apply this globally. Either of these would allow you to take the filterLevel and filterDate fields out of your route definition and still get the scope you want. Then it should be no problem to pass the parameters in a querystring with Html.ActionLink().
To do this with the route handler, change your route definition to:
routes.Add(
new Route(
"{controller}/{action}/{id}",
new RouteValueDictionary(new{ controller = "Home", action = "Index", id = UrlParameter.Optional}),
new CustomRouteHandler()));
Your implementation of the route handler would be something like this:
public class CustomRouteHandler : IRouteHandler
{
public IHttpHandler GetHttpHandler(RequestContext requestContext)
{
var routeValues = requestContext.RouteData.Values;
if(!routeValues.ContainsKey("filterLevel"))
{
routeValues.Add("filterLevel","INFO");
}
if(!routeValues.ContainsKey("filterDate"))
{
routeValues.Add("filterDate", DateTime.Now.AddDays(-1));
}
var mvcRouteHandler = new MvcRouteHandler();
return (mvcRouteHandler as IRouteHandler).GetHttpHandler(requestContext);
}
}
I thought the defaults were always for entries defined in the URL, that you can't define a default to omit something not in the core URL, and anything else is passed as a querystring.
Interesting question.
HTH.
You should specify the default value in your method, like this:
public ActionResult Machine(string id, DateTime? filterDate = null, string filterLevel = "INFO")
{
filterDate = filterDate ?? DateTime.Now.AddDays(-1);
var model = new LogListViewModel { LogEntries = logEntries };
return View(model);
}
If there are default values that are not specified in the URL pattern, then you can't override them because they are used to determine route selection when matching routes for URL generation.
Let me give you an example. Suppose you had the following two routes.
routes.MapRoute(
"Default1", // Route name
"foo/{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional
, filterLevel = "INFO" } // Parameter defaults
);
routes.MapRoute(
"Default2", // Route name
"bar/{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional
, filterLevel = "DEBUG" } // Parameter defaults
);
Notice that there's a default value for "filterLevel", but there is no "{filterLevel}" parameter within the URL pattern.
Which URL should match when you do this?
#Html.ActionLink(item.MachineName, "Machine",
new { id = item.MachineName, filterLevel = "RANDOM" }, null)
If you could override the default value for filterLevel, then you'd expect both of the routes to match. But that doesn't make sense. In this case, neither matches because filterLevel isn't in the URL pattern and therefore the supplied filterLevel must match the default value. That way, you can do this:
#Html.ActionLink(item.MachineName, "Machine",
new { id = item.MachineName, filterLevel = "INFO" }, null)
//AND
#Html.ActionLink(item.MachineName, "Machine",
new { id = item.MachineName, filterLevel = "DEBUG" }, null)
to generate a URL for the first and second route respectively.
This confusion is why I always recommend to always use named routes.

Resources