Such as I get a filter model:
public class Filter
{
public int Id{get;set;}
public string Name{get;set;}
public DateTime CreateTime{get;set;}
}
And there is a SearchController action like:
public ActionResult Search(Filter filterModel)
{
List<Model> model =SampleBll.get(filterModel)
}
so the question is.How to configure URL like
/Search/{Filter.Id}_{Filter.Name}_{Filter.CreatTime}/
Thank you for your help
You can treat {Filter.Id}_{Filter.Name}_{Filter.CreatTime} as string filter and parse it in your controller.
public ActionResult Search(string filter)
{
var parts = filter.Split("|".ToCharArray());
Filter model = new Filter();
model.Id = Int32.Parse(parts[0]);
// ...
}
You would first need to add the following route into your Global.asax.cs RegisterRoutes method, before the default route:
routes.MapRoute(
"Search", // Name
"Search/{Id}_{Name}_{CreateTime}", // url format
new { controller = "Search", action = "Search" } // Defaults
);
Once this is done, going to your application using a url such as /Search/123_Test_06-01-2011 would trigger the route, and the built-in object mapping will take care of mapping the properties to the model as long as the parameter names in the route match the names of the property and they can be successfully cast to the corresponding type.
Use string or change _ per / {Filter.Id}/{Filter.Name}/{Filter.CreatTime}
Related
I'm trying to bind a single parameter of a URL query to a single property in an action method.
The URL is along the lines of:
/user/validate?Some.Prefix.Username=MyUserName
And my controller and action method are along the lines of:
public class UserController : Controller
{
public IActionResult Validate([Bind(Prefix = "Some.Prefix")]string username)
{
return Ok(username);
}
}
However the username parameter is always null when this action method is called. It seems this is a result of using the BindAttribute with a string parameter, rather than a simple class parameter. If I replace the string username parameter with a simple class containing a Username property, I can capture the value as expected.
public class UserController : Controller
{
public IActionResult Validate([Bind(Prefix = "Some.Prefix")]ValidationModel model)
{
return Ok(model);
}
}
public class ValidationModel
{
public string Username { get; set; }
}
Is there any way to bind to a single parameter (rather than a class parameter) when the URL parameter name contains prefixes?
For simple types like int and string, the Bind Prefix overrides the model name for the parameters. Using your action method as an example, the DefaultModelBinder would be looking for the name "Some.Prefix" instead of "username".
So, if you want to work around this and not require a complex type, you need to specify the fully qualified name.
public IActionResult Validate([Bind(Prefix = "Some.Prefix.Username")]string username)
I'm using ASP.NET Core, and attribute routing.
I have this strongly typed model
public Command
{
public int Id { get; set; }
}
And this action
[HttpPost]
[Route("my route here")]
public IActionResult Foo(Command command) { ... }
So route looks like this
.../whatever/foo?id=5
But I want
.../whatever/foo/5
I tried changing the property to int? but that doesn't help.
You can define your route with input parameters in it.
.../whatever/foo/{id}
If you want to access the supplied parameter, you can add it as a method parameter.
public IActionResult Foo(Command command, int id) { ... }
In my controller of an ASP.NET MVC project, I have a
return RedirectToAction("CreatePerson", "Home")
This View is a form that creates a person and that works fine. However, I want to RedirectToAction and pre-fill the form with data collected from a form that creates a User for the system.
How would I pass the data from the CreateUser form in the CreatePerson form?
I know that I could use parameters, but would this really be the best method if most of the time I am calling the CreatePerson view without needing those parameters.
Any help in the right direction would be greatly appreciated.
You can't send data with a RedirectAction. That's because you're doing a 301 redirection and that goes back to the client.
So better use TempData
Assuming you will have model to createperson with following properties:
public class CreatePersonData
{
public string name {get; set;}
public string address {get; set;}
}
Now fill the model and store in TempData
CreatePersonData person=new CreatePersonData();
person.name="SomeName";
person.address="SomeAddress";
TempData["person"]=person;
return RedirectToAction("CreatePerson", "Home")
Now while receiving just receive it from tempdata and pass the filled model to the view
public ActionResult CreatePerson()
{
CreatePersonData person=new CreatePersonData()
var loadPerson= TempData["person"];
person = loadPerson;
return View(person);
}
UPDATE
As #StephenMuecke made a point of loosing data with TempData you might need to use .Keep or .Peek with TempData to retain the value for future requests
Ex:
with .Peek
//PEEK value so it is not deleted at the end of the request
var loadPerson= TempData.Peek("person");
or with .Keep
//get value marking it from deletion
var loadPerson = TempData["person"];
//later on decide to keep it
TempData.Keep("person");
or as #Stephen said just pass the id and select the user from database
Ex:
return RedirectToAction("CreatePerson", "Home", new { ID = User.ID });
Now in your CreatePerson ActionResult just get it from db as below:
public ActionResult CreatePerson(int ID)
{
CreatePersonData person=new CreatePersonData();
var user=(from u in tbl_user select u where u.ID=ID);
person.name=user.name;
person.address=user.address;
return View(person);
}
UPDATE 2
You can combine both of the above approaches like storing data in TempData and passing the ID with routeValues and check if TempData isn't null then fallback to retrieval of data using ID approach.
Ex:
public class CreatePersonData
{
public string Id{get; set;}
public string name {get; set;}
public string address {get; set;}
}
public ActionResult CreatePerson(int ID)
{
CreatePersonData person=new CreatePersonData();
var loadPerson=(CreatePersonData)TempData.Peek("person"); //cast the object from TempData
if(loadPerson!=null && loadPerson.Id==ID)
{
person=loadPerson;
}
else
{
var user=(from u in tbl_user select u where u.ID=ID);
person.name=user.name;
person.address=user.address;
}
return View(person);
}
Many Overloads exist for this
protected internal RedirectToRouteResult RedirectToAction(string actionName, object routeValues);
What you want to do is right click on that Method and View Definition, you should see many overloads for it
// Summary:
// Redirects to the specified action using the action name and route values.
//
// Parameters:
// actionName:
// The name of the action.
//
// routeValues:
// The parameters for a route.
//
// Returns:
// The redirect result object.
1- create an object of your model
2- you can use session to pass parameter to your other action,
3- then put the object in a viewbag agg get it in your view
Is there any way to alter the passed object to an action-method before it actually enters/(gets passed to) the action-metod?.. For instance...
By default I want the Index()-action-method to always take an argument of MyClass..
So.. if a user visit mydomain.com/AController/
The triggerd action-method should be
public ActionResult Index(MyClass arg)
{
return View();
}
Im not really sure of how to explain this.. but hopefully you get it..
What I actually want to do is the same thing that Umbraco does in thier MVC-project.. where they always pass-along a RenderModel-object, except that I want to have my own type not the RenderModel..
Thanks in advance!
As I understand your question, you want your action being invoked with a default arg value (if none is provided)
Considering your MyClass as :
public class MyClass
{
public int Id { get; set; }
public string Name { get; set; }
}
You may define your route like :
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{arg}",
defaults: new { controller="Home",
action = "Index",
arg = new MyClass() { Id = 1, Name = "test" }
}
);
I guess another option would be to have a custom ModelBinder or, at lower level, a custom ValueProvider.
Provided your class is simple enough, there should be no need to intercept the call to the action.
For example, if the class has a properties of int, string and DateTime, even IEnumerable<int> etc, then MVC will map form post data or a querystring to the class automatically.
So, a URL like example.com/your-path/?id=1&categories=3,4,56&tags=this,that would automatically map to a class like:
public YourClass
{
public int Id { get; set; }
public IEnumerable<int> Categories { get; set; }
public IEnumerable<string> Tags { get; set; }
}
If you need to do additional work with the data, for example, if you are posting XML/JSON and need to deserialize it before populating your class, then #jbl's answer is the one for you.
From an Umbraco perspective, if you are hijacking your controllers, then you could simply add your class to the Index() action as an additional parameter, e.g. Index(RenderModel model, YourClass arg). This would pick up and populate any additional data pass to your page.
The problem with #jbl's approach with Umbraco is that Umbraco handles the routing for you, so you can not specify your own routing without bypassing Umbraco's controllers entirely - which defeats the purpose of using Umbraco :)
I'm trying to extract the parameters of my URL, something like this.
/Administration/Customer/Edit/1
extract: 1
/Administration/Product/Edit/18?allowed=true
extract: 18?allowed=true
/Administration/Product/Create?allowed=true
extract: ?allowed=true
Someone can help? Thanks!
Update
RouteData.Values["id"] + Request.Url.Query
Will match all your examples
It is not entirely clear what you are trying to achieve. MVC passes URL parameters for you through model binding.
public class CustomerController : Controller {
public ActionResult Edit(int id) {
int customerId = id //the id in the URL
return View();
}
}
public class ProductController : Controller {
public ActionResult Edit(int id, bool allowed) {
int productId = id; // the id in the URL
bool isAllowed = allowed // the ?allowed=true in the URL
return View();
}
}
Adding a route mapping to your global.asax.cs file before the default will handle the /administration/ part. Or you might want to look into MVC Areas.
routes.MapRoute(
"Admin", // Route name
"Administration/{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
If it's the raw URL data you are after then you can use one of the various URL and Request properties available in your controller action
string url = Request.RawUrl;
string query= Request.Url.Query;
string isAllowed= Request.QueryString["allowed"];
It sounds like Request.Url.PathAndQuery could be what you want.
If you want access to the raw posted data you can use
string isAllowed = Request.Params["allowed"];
string id = RouteData.Values["id"];
public ActionResult Index(int id,string value)
This function get values form URL
After that you can use below function
Request.RawUrl - Return complete URL of Current page
RouteData.Values - Return Collection of Values of URL
Request.Params - Return Name Value Collections
You can get these parameter list in ControllerContext.RoutValues object as key-value pair.
You can store it in some variable and you make use of that variable in your logic.
I wrote this method:
private string GetUrlParameter(HttpRequestBase request, string parName)
{
string result = string.Empty;
var urlParameters = HttpUtility.ParseQueryString(request.Url.Query);
if (urlParameters.AllKeys.Contains(parName))
{
result = urlParameters.Get(parName);
}
return result;
}
And I call it like this:
string fooBar = GetUrlParameter(Request, "FooBar");
if (!string.IsNullOrEmpty(fooBar))
{
}
In order to get the values of your parameters, you can use RouteData.
More context would be nice. Why do you need to "extract" them in the first place? You should have an Action like:
public ActionResult Edit(int id, bool allowed) {}
I'm not familiar with ASP.NET but I guess you could use a split function to split it in an array using the / as delimiter, then grab the last element in the array (usually the array length -1) to get the extract you want.
Ok this does not seem to work for all the examples.
What about a regex?
.*(/|[a-zA-Z]+\?)(.*)
then get that last subexpression (.*), I believe it's $+ in .Net, I'm not sure