in my Asp.net MVC2 app I have registered the following routes in the global.asax.cs:
routes.MapRoute(
"Search",
"Search/{action}/{category}/{query}/{page}",
new { controller = "Search", action = "Results", category = "All", page = 1 },
new { page = #"\d{1,8}" }
);
// URL: /Search
routes.MapRoute(
"SearchDefault",
"Search",
new { controller = "Search", action="Index" }
);
routes.MapRoute(
"Product",
"Product/{action}/{productcode}",
new { controller = "Product", action = "Details" }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Search", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
I have my SearchController:
public ActionResult Results(string category, string query, int page)
{
}
I have my ProductController:
public ActionResult Details(string productcode)
{
return View();
}
In my Results.aspx View, the following ActionLinks exist:
<% foreach (var cat in Model.Categories) { %>
<li><%= Html.ActionLink(cat.Name, "Results", "Search", new { category= cat.Name, query = Model.SearchText, page=1 }, null)%></li>
<% } %>
</ul>
<hr />
<table>
<% foreach (var p in Model.Products) { %>
<tr>
<td>
<%= Html.ActionLink(p.ProductName, "Details", "Product", new { product = p.ProductCode }, new { })%><br />
</td>
</tr>
<% } %>
The first actionlink is rendering as:
"http://localhost/Search/Results?category=Test%20Category%20A&query=test%20product&page=1"
whereas the second ActionLink is correctly rendering:
"http://localhost/Product/Details/1234ABC020848"
The strange thing is that both work correctly and even if I manually type in:
"http://localhost/Search/Results/Test%20Category%20A/test%20product/1"
then my SearchController correctly executes also. I really would rather have the cleaner URL rendered by my ActionLink. What have I missed?
Thanks in advance.
As I donĀ“t have your model, I did remove the foreach loops and I replace all unknown values by strings. In my tests I found the opposite behavior: the first link was ok while the other was not cleaner. The fix for the second action link was to replace "product" by "productcode".
<ul>
<li><%= Html.ActionLink("Category", "Results", "Search", new { category= "Test Category A", query = "test product", page=2 }, null)%></li>
</ul>
<hr />
<table>
<tr>
<td>
<%= Html.ActionLink("Product", "Details", "Product", new { productcode = "1234ABC020848" }, new { })%><br />
</td>
</tr>
</table>
Both ways are suppose to work as the routing system is responsible for mapping the variables.
routes.MapRoute(
"SearchDefault",
"{controller}/{action}/{category}/{query}/{page}",
new { },
new { controller = "Search", action = "Results" }
);
This should get you url like this (some additional tweaks may be required)
http://localhost/Search/Results/Test%20Category%20A/test%20product/1
Ignore that... I didn't see the first route in the question.
I usually like to use query string for searches tho, because once you got two or more parameters that aren't required, routes for that are kinda pain to build and maintain.
Related
I need to loop through an object PostIts and display the "Id", " Title" with an ejs "forEach" Loop Am using sails.js "1.2.3" and mongodb on local host, but i get error
ReferenceError : postIts is not defined at eval (eval at compile ?
Here is the code on the PostItsController.js:
module.exports = {
list: function(req, res) {
// res.view('list');
PostIts.find({}).exec(function(err, postIts) {
if (err) {
res.send(500, { error: 'Database Error' });
}
res.view('list', { postIts: postIts });
});
}
};
And here is the code on list.ejs:
<tbody>
<% postIts.forEach(function(postit){ %>
<tr>
<td>
<%= postit.id %>
</td>
<td>
<%= postit.title %>
</td>
<td></td>
</tr>
<% }) %>
</tbody>
I should get the value of the ID and title displayed on the list.ejs page in a table, but instead I get an error that the postIts object is not defined.
First of all your route '/postIts/list': { view: 'list' }, should point to an action (since it has backend logic) not a view, so in your case "/postIts/list": "PostItsController.list", but if you're using actions2 things would be simpler
Secondly you don't need to tell your users that you have a database error error: "Database Error"
Using Actions2
sails generate action post/list
In your config/route.js
'POST /api/v1/post/list': { action: 'post/list' },
In your action
module.exports = {
friendlyName: "List Posts",
description: "List all post in our site",
inputs: {},
exits: {
success: {
description: "The path to your template file",
viewTemplatePath: "list"
}
},
fn: async function(inputs) {
var posts = await Post.find();
// All done.
return { postIts: posts };
}
};
postit works
An Boohoo! it works
https://sailsjs.com/documentation/concepts/actions-and-controllers/routing-to-actions
If you're sure that res.view('list', { postIts: postIts }); is actually sending the correct data you can use _.each(postIts, cb()) ... instead
For some reason the postIts object didnt save the data from the post req I made instead it just recalled what I posted. and I used the '_.each(postIts, function (postit)' and it finally worked.
to me its like a magic happened hahaha but yeah I learned from it.
thanks #Navicstein Rotciv for the quick replies.
I am having problems binding the selected value of a selectbox to a property within the view model. For some reason it keeps coming back unchanged when posted back to the server.
My Html is:
<form action="/Task/Create" data-bind="submit: save">
<table border="1">
<tr>
<td>ref type</td>
<td><select data-bind="options: ReferenceTypes, optionsText: 'Name', optionsCaption: 'Select...', value:Task.ReferenceTypeId"></select></td>
<td>Reference</td>
<td><input data-bind="value:Task.Reference" /></td>
</tr>
</table>
<button type="submit">Save Listings</button>
</form>
The Javascript is:
<script type="text/javascript">
var viewModel = {};
$.getJSON('/Task/CreateJson', function (result) {
viewModel = ko.mapping.fromJS(result.Data);
viewModel.save = function () {
var data = ko.toJSON(this);
$.ajax({
url: '/Task/Create',
contentType: 'application/json',
type: "POST",
data: data,
dataType: 'json',
success: function (result) {
ko.mapping.updateFromJS(viewModel, result);
}
});
}
ko.applyBindings(viewModel);
});
</script>
JSON from Fiddler that gets loaded into the page as below.
{
"ContentEncoding":null,
"ContentType":null,
"Data":{
"Task":{
"ReferenceTypeId":0,
"Reference":"Default Value"
},
"ReferenceTypes":[
{
"Id":2,
"Name":"A Ref Type"
},
{
"Id":3,
"Name":"B Ref Type"
},
{
"Id":1,
"Name":"C Ref Type"
}
]
},
"JsonRequestBehavior":1
}
This comes back into the server (ASP.NET MVC3) correctly, with the updated Reference string value, but ReferenceTypeId is not bound to the correctly selected drop down value. Do I need to perform any additional functions to bind correctly etc? Or tell the data-bind what the select value column is (Id) etc? I have checked in Fiddler on the values getting posted back from the browser, and it has the same original value (0). So it is definately not the server.
I hope someone can help, if you need any further information please ask.
Kind Regards
Phil
The issue is that your options binding will try to assign the object that it is bound to, to the value observable specified.
For example if you select "A Ref Type" the options binding will push the json object
{ "Id":2, "Name":"A Ref Type" }
Into your Task.ReferenceTypeId observable which will then be serialized back to your server. In this case you need to add an optionsValue config options to tell the binding just to save the id.
<select data-bind="options: ReferenceTypes, optionsText: 'Name',
optionsCaption: 'Select...', optionsValue: 'Id', value:Task.ReferenceTypeId">
</select>
Here's an example.
http://jsfiddle.net/madcapnmckay/Ba5gx/
Hope this helps.
I have an application that in the admin area there is options such as
Background image: [ File Upload ]
Top Illustration: [ File Upload ]
and in the front end I want to easily attach this info to the CSS, maybe teh simply way should be
.background {
background: url(<%: Model.BackgroundUrl %>);
...
}
I currently have my Css files unde ~/Content/Css
shall I have a View with this and change the content type so I can use the Model part?
What other techniques are available or this situation?
Thank you.
You cannot use the model in a static CSS file. If you want to achieve this you will need to generate it dynamically using a controller action. As an alternative you could directly use an img tag:
<img src="<%: Model.BackgroundUrl %>" alt="" />
I ended up doing a new View and set all up as:
in the Master Template
<link href="<%= Url.Content(
String.Format("~/{0}/Css/CustomCss.aspx",
ViewData["CalendarUrl"])) %>"
rel="stylesheet" type="text/css" />
in the Routes
routes.MapRoute(
"CustomCss", // Route name
"{calurl}/Css/CustomCss.aspx", // URL with parameters
new { calurl = "none", controller = "Content", action = "CustomCss", id = UrlParameter.Optional } // Parameter defaults
);
in the Controller: Content, Action: CustomCss
// GET: /Css/CustomCss
public ActionResult CustomCss(string calurl)
{
return View();
}
in my View (placed in Shared):
<%# Page Language="C#" Inherits="System.Web.Mvc.ViewPage<dynamic>"
ContentType="text/css" %>
<%
string company_logo = ViewData["CompanyLogo"] as string;
string company_bkg = ViewData["CompanyBackground"] as string;
%>
.background {
<%if (!String.IsNullOrWhiteSpace(company_bkg))
{ %>background-image:url('<%: company_bkg %>');<%} %>
}
#header-content{
<%if (!String.IsNullOrWhiteSpace(company_logo ))
{ %>background-image:url('<%: company_logo %>');<%} %>
}
I'm trying to use Html.ActionLink to generate a link with in this form:
/Action/Model/Id/Parameter1/Parameter2
I've used:
<%= Html.ActionLink("Link Text", "Action", "Model", new { id = var, parament1=var1 }, null) %>
but it always ends up looking like /Action/Model/Id?parameter1=variable
I've seen similar questions on Stackoverflow and elsewhere, but I can't find a solution that works/makes sense. Any help would be appreciated.
#John: I have the following route registered: routes.MapRoute("Alternate","{controller}/{action}/{id}/{Heading}", new { controller = "Designation", action = "Details", id = "", Heading = "" }
I then have the following code in my view: <%= Html.ActionLink("Link Text", "Action", "Model", new { Id = model.Id, Heading = model.Heading }, null) %>
I get /Model/Action/Id?Heading=var1 I want it as /Model/Action/Id/var1
ANSWER: I added the following route to my global.asax.cs file and the links generated correctly.
routes.MapRoute("Something", "MyModel/MyAction/{Id}/{Heading}", new { controller = "MyModel", action = "MyAction", id = "", heading = "" }, new { controller = #"[^.]*" });
I have the following default and only route:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
In my Site.Master I have the following:
<%= Html.ActionLink("Profile", "Details", "Users")%>
If I am on the following Url:
http://localhost:1155/Users/Details/1
and I click the link above it goes the same page.
Should it not go to the following url?
http://localhost:1155/Users/Details
For some reason it is keeping the id in the Url.
For some reason it is keeping the id in the Url.
It is by design.
Try this to get rid of id:
<%= Html.ActionLink("Profile", "Details", "Users", new { id = "" }, null)%>