Encode dataview value in ASP.NET MVC Actionlink - ajax

I am using the Microsoft Ajax Template DataView to bind values to a template. I can do this and it works as you'd expect:
<h3>{{ID}}</h3>
<p>{{Address}}</p>
However I am trying to build an action link that has the ID in it.
<h2><%= Html.ActionLink(Html.AttributeEncode("{{Name}}"), "Index", "Restaurant", new { Id = Html.AttributeEncode("{{ID}}") }, null)%></h2>
The name is shown as the link text as I wanted but the link doesn't include the ID, instead it has %7B%7BID%7D%7D
How would I get the Id to be properly parsed and added to the link?

It's possible that the extra brackets are throwing it off. Try assigning the values to variables and using the variables in the ActionLink. You could do the assignment at the top of the view and then reuse them throughout the view as well. to keep from having to re-encode them everywhere.
<% var id = Html.AttributeEncode( "{{ID}}" );
var name = Html.AttributeEncode( "{{Name}}" );
%>
<h2><%= Html.ActionLink(name, "Index", "Restaurant", new { Id = id }, null)%></h2>

Finally got it to work, I don't know if I was being stupid or if it's the lack of documentation but here is how to bind the dataview value to a link.
<h2><a sys:href="{{'Restaurant/Index/' + ID}}">{{Name}}</a></h2>
The actual url route part needs to be in single quotes and you need to use sys:href instead of href.

Its good practice to include '<%= Url.Action("Index", "Restaurant")%>' when builing a manual url to avoid problems with the application name and conflicting urls.

Related

Routing: Forward slashes are still encoded when using a double-asterisk (**) catch-all parameter syntax

I would like to use url parameter with forward slash in it (for better looking url).
I've set up routing as shown in MS docs with double asterisk:
mvcRoutes.MapRoute(
name: "processRequest",
template: "{lang}/{**path}",
defaults: new { controller = "DisplayContent", action = "ProcessRequest", lang = "en" });
Route is picked up and parameters are passed correctly to action if I enter url like www.example.com/en/s/link.
The problem arises when I try to generate links based on this route.
Url.RouteUrl("processRequest", new { lang = 'en', path = "s/link" })
gives
/en/s%2flink
The same thing happens when I use anchor tag helper in razor.
<!-- GetQueryParameters is a method that returns query parameters as Dictionary<string, string> -->
<a asp-route="processRequest" asp-all-route-data="#ViewContext.GetQueryParameters()">Test</a>
<a asp-route="processRequest" asp-route-lang="en" asp-route-path="s/link">Test</a>
Both of these sets href to
/en/s%2flink.
Is it possible to generate these links using helpers or do I have to settle with manually creating string and setting href without using tag helpers?
Looks like I got it working. Changed so many things (multiple routing paths, anchor tag helper calls).
But one thing I can say for sure that breaks this is removing compatibility version.
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2)
I had removed this at some point, but after adding it back the links are created as I want.

I seem to be getting a GUID in the MvcSiteMapProvider Breadcrumb trail, not sure why?

I am using MVC3, C#, Razor, mvcSiteMapProvider V4.
I am using "Mvc.sitemap"
<mvcSiteMapNode title="Reports" controller="Report" action="Index" preservedRouteParameters="ClientId" route="Report">
<mvcSiteMapNode key="Report_Section" title="Sections" controller="Section" action="FilterByReport" preservedRouteParameters="ClientId,ReportId" route="Report_Section">
<mvcSiteMapNode key="Background" title="Background" controller="Wizard" action="Index" preservedRouteParameters="ClientId,ReportID,SectionID,SectionName" route="Background"/>
The "Global.asax" custom routes look like:
routes.MapRoute("Report", "Report/{ClientId}", new { controller = "Report", action = "Index", ClientId = UrlParameter.Optional });
routes.MapRoute("Report_Section", "Report/{ClientId}/Section/{ReportId}", new { controller = "Section", action = "FilterByReport", ReportId = UrlParameter.Optional });
routes.MapRoute("Background", "Report/{ReportID}/SectionID/{SectionID}/SectionName/{SectionName}", new { controller = "Wizard", action = "Index", ReportID = UrlParameter.Optional, SectionID = UrlParameter.Optional, SectionName = UrlParameter.Optional });
The "Report" and "Report_Section" routes work fine. However when I go into the "Background" route I lose all of my route structure, for the "Report_Section" and "Report" routes, in the mvcSiteMap BreadCrumb URL. Instead I get a GUID ie:
http://localhost/7ebe9bb9-a663-43fd-9fb1-865866be12b9
I believe this might be the XML Node Key that is autogenerated. However it prodocues a 404 when clicked.
I should get something like:
Reports
http://localhost/Report/10
Sections
http://localhost/Report/10/Section/100
Any ideas what could be causing this?
Thanks.
You will get a Guid for the URL if the URL resolver cannot find a match. Throwing an exception in this case was causing other issues (see why does URL resolver throw an exception).
However, I can't tell you exactly why it is not matching without seeing more of your configuration. A clue is that we are using UrlHelper.RouteUrl(string, RouteValueDictionary) to resolve the URL. You can try calling it explicitly with your route values and route name. Also, see the source code for other clues.
One thing I noticed that looks off is that you are preserving the ClientID route parameter for Background when it is not even used in that route. Keep in mind that preserving route parameters only copies them from the current HTTP request and your other nodes will appear to forget them.
PreserveRouteParameters is typically used for CRUD operations where you make data editing pages. If you want it to appear to "remember" the user's navigation path, then you need to add 1 node per unique route value combination to your sitemap.
If the above doesn't help, please create a small demo project that exhibits the problem and either upload it to GitHub or else zip it and make it available for download, then open a new issue at GitHub with the link to the demo.

column template kendo ui grid mvc action link

The following code is working fine in development, as soon as i deploy in web server it said could find file directory. I need to change the .client template so its not hard coded like before. So if we deploy to the server where the Top folder name different or the hierarchy change, it still find the page.
I was thinking using #Url.Action but not sure how in this case to implement in .CLientTemplate
columns.Template(#<text>
#Html.ActionLink(#item.FirstName, "Index", "Summary", new { testId = #item.FirstName })
</text>)
.ClientTemplate("<a href='/Summary/Index/?testId =#= TestId #'>#=FirstName#</a>").Title("First Name");
Something like this should do:
.ClientTemplate("<a href='" + Url.Action("Index", "Summary", new { testId = "#=TestId#" }) + "'>#=FirstName#</a>")
I got this one working fine
columns.Bound(a => a.Id)
.Title("Action")
.Filterable(false)
.ClientTemplate(
"<a href='"
+ Url.Action("ActionName", "Controller")
+ "/#= Id #'"
+ ">View</a>"
);
I needed an extra column and a link button field for go to details page of a customer. I don't need filter option for this column and that is why I remove it using Filterable(false). Also you can give the link content and column header as above. This value "/#= Id #'" is the one I pass to the controller action method.
In case you're using server-binding (as opposed to ajax) and Razor as your view-engine, here is an example. I need a link such as /Controller/Action/Id where Id is obtained from a property of the model. Please note that #item denotes the model instance being currently processed by the grid.
columns.Template(#<text>#Html.ActionLink(AbaScore.Resources.App.Edit,"ACTION", "CONTROLLER", new { #item.Id }, null)</text>)
I've seen 87 different examples of this and none of them worked. This is what I finally did and it worked, and it's simple as heck.
columns.Bound(p => p.member_id)
.ClientTemplate("<a href='/members/details/#=member_id#'>Details</a>")
;

Issue with wrong controller being called in jquery ajax call

My issue is for some strange reason it seems stuck in the page controller so instead of getting out and going into the ajax controller I have it trying to go down that route in the page controller
1st try
http://localhost:2185/Alpha/Ajax/GetBlah_Name/?lname=Ge&fname=He
2nd try
http://localhost:2185/Patient/~/Ajax/GetBlah_Name/?lname=Ge&fname=He
Objective
http://localhost:2185/Ajax/GetBlah_Name/?lname=Ge&fname=He
Page button to call jquery
<a style="margin-left: 310px;" href="javascript:void(0)" onclick="getBlah()"
class="button"><span>Lookup</span></a>
Jquery code
1st try
{
$.getJSON(callbackURL + 'Ajax/GetBlah_Name/?lname=' + $('#Surname').val() + '&fname=' + $('#FirstName').val(), null, GetResults)
}
2nd try
{
$.getJSON(callbackURL + '~/Ajax/GetBlah_Name/?lname=' + $('#Surname').val() + '&fname=' + $('#FirstName').val(), null, GetResults)
}
In summary I don't know why it won't break out of the controller and go into the Ajax controller like it has done so in all the other projects I've done this in using the 1st try solution.
It seems you want to cal a controller at ~/Ajax. Is it? If yes, you should use this code:
$.getJSON(callbackURL + '/Ajax/GetBlah_Name/?lname=' + $('#Surname').val() + '&fname=' + $('#FirstName').val(), null, GetResults)
UPDATE:
This will work for your Q, but the complete solution is #Darin Dimitrov's answer. I suggest you to use that also.
UPDATE2
~ is a special character that just ASP.NET works with it! So http doesn't understand it. and if you start your url with a word -such as Ajax-, the url will be referenced from where are you now (my english is not good and I can't explain good, see example plz). For example, you are here:
http://localhost:2222/SomeController/SomeAction
when you create a link in this page, with this href:
href="Ajax/SomeAction"
that will be rendered as
http://localhost:2222/SomeController/Ajax/SomeAction
But, when url starts with /, you are referring it to root of site:
href="/Ajax/SomeAction"
will be:
http://localhost:2222/Ajax/SomeAction
Regards
There are a couple of issues with your AJAX call:
You are hardcoding routes
You are not encoding query string parameters
Here's how I would recommend you to improve your code:
// Always use url helpers when dealing with urls in an ASP.NET MVC application
var url = '#Url.Action("GetBlah_Name", "Ajax")';
// Always make sure that your values are properly encoded by using the data hash.
var data = { lname: $('#Surname').val(), fname: $('#FirstName').val() };
$.getJSON(url, data, GetResults);
Or even better. Replace your hardcoded anchor with one which will already contain the lookup url in its href property (which would of course be generated by an url helper):
<a id="lookup" href="Url.Action("GetBlah_Name", "Ajax")" class="button">
<span>Lookup</span>
</a>
and then in a separate javascript file unobtrusively AJAXify it:
$(function() {
$('#lookup').click(function() {
var data = { lname: $('#Surname').val(), fname: $('#FirstName').val() };
$.getJSON(this.href, data, GetResults);
return false;
});
});
Now how your urls will look like will totally depend on how you setup your routes in the Application_Start method. Your views and javascripts are now totally agnostic and if you decide to change your route patterns you won't need to touch jaavscript or views.

Getting raw text using #Html.ActionLink in Razor / MVC3?

Given the following Html.ActionLink:
#Html.ActionLink(Model.dsResults.Tables[0].Rows[i]["title"].ToString(), "ItemLinkClick",
new { itemListID = #Model.dsResults.Tables[0].Rows[i]["ItemListID"], itemPosNum = i+1 }, ...
Data from the model contains HTML in the title field. However, I am unable to display the HTML encoded values. ie. underlined text shows up with the <u>....</u> around it.
I've tried Html.Raw in the text part of the ActionLink, but no go.
Any suggestions?
If you still want to use a helper to create an action link with raw HTML for the link text then I don't believe you can use Html.ActionLink. However, the answer to this stackoverflow question describes creating a helper which does this.
I would write the link HTML manually though and use the Url.Action helper which creates the URL which Html.ActionLink would have created:
<a href="#Url.Action("ItemLinkClick", new { itemListID = #Model.dsResults.Tables[0].Rows[i]["ItemListID"], itemPosNum = i+1 })">
#Html.Raw(Model.dsResults.Tables[0].Rows[i]["title"].ToString())
</a>
MVCHtmlString.Create should do the trick.
Using the actionlink below you do not need to pass html in the model. Let the css class or inline style determine how the href is decorated.
#Html.ActionLink(Model.dsResults.Tables[0].Rows[i]["title"], "ItemLinkClick", "Controller", new { #class = "underline", style="text-decoration: underline" }, null)
those are the cases that you should take the other path
#{
string title = Model.dsResults.Tables[0].Rows[i]["title"].ToString(),
aHref = String.Format("/ItemLinkClick/itemListID={0}&itemPosNum={1}...",
Model.dsResults.Tables[0].Rows[i]["ItemListID"],
i+1);
}
#Html.Raw(title)
Remember that Razor helpers, help you, but you can still do things in the HTML way.
You could also use this:
<a class='btn btn-link'
href='/Mycontroler/MyAction/" + item.ID + "'
data-ajax='true'
data-ajax-method='Get'
data-ajax-mode='InsertionMode.Replace'
data-ajax-update='#Mymodal'>My Comments</a>

Resources