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
Related
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
I'm using remote validation with complex type. As the name of my field can be something like name="user.name", I need to use the BindAttribute like that
public JsonResult ValidName[Bind(Prefix="user.name")]string name){ ... }
or the binding will not work.
The problem is that there will be many different name that end with "user.name" like "employee.user.name" or "manager.user.name".
So, is it possible to bind all field where the name end with "user.name" to string name in the method declaration?
You are misunderstanding the use of Prefix. Its for identifying what a complex property name (dot notation) starts with, not ends with. If for example you had a view model MyModel with a complex property Organisation with a complex property Address with a property City then in you view, you might have
#model MyModel
#Html.TextBoxFor(m => m.Organisation.Address.City)
would render the following html
<input name="Organisation.Address.City" ...... />
If you only wanted to post back the value of City then you would use
public ActionResult Edit([Bind(Prefix="Organisation.Address")] string city)
Similarly if you only wanted to post back all values of Address, it would be
public ActionResult Edit([Bind(Prefix="Organisation")] Address address)
{
string city = address.City;
So in your case above, you would need both
public JsonResult ValidName[Bind(Prefix="employee.user")] string name)
and
public JsonResult ValidName[Bind(Prefix="manager.user")] string name)
You can use Request.QueryString to manually bind the parameter that you want in the controller method. Here is a quick code to bind the first parameter that end with the specified suffix
private bool EndWith(string input, string end)
{
string pattern = #"" + end + #"$";
Regex rx = new Regex(pattern, RegexOptions.IgnoreCase);
return rx.Match(input).Success;
}
private string bindSuffix(string suffix)
{
string result = null;
foreach (var key in Request.QueryString.AllKeys)
{
if (EndWith(key, suffix))
{
result = Request.QueryString[key];
}
}
return result;
}
//Then use it like that
public JsonResult ValidName()
{
string name = bindSuffix("user.name");
...
}
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}
I want to pass more then one parameter from RedirectToAction method
how can I pass?
My One Action Method
[HttpPost, ActionName("SelectQuestion")]
public ActionResult SelectQuestion(string email,List<QuestionClass.Tabelfields> model)
{
List<QuestionClass.Tabelfields> fadd = new List<QuestionClass.Tabelfields>();
for (int i = 0; i < model.Count; i++)
{
if (model[i].SelectedCheckbox == true)
{
List<QuestionClass.Tabelfields> f = new List<QuestionClass.Tabelfields>();
fadd.Add(model[i]);
}
}
return RedirectToAction("Question", new { email = email, model = fadd.ToList() });
}
My another Action Method
[HttpGet]
public ActionResult Question(string email,List<QuestionClass.Tabelfields> model)
{
}
I am not getting values in model.
You cannot pass a collection of complex objects in urls when redirecting.
One possibility would be to use TempData:
TempData["list"] = fadd.ToList();
return RedirectToAction("Question", new { email = email});
and then inside the Question action:
var model = TempData["list"] as List<QuestionClass.Tablefields>;
The way that I solved this problem was to serialize the list to a JSON object using the JsonConvert method from the Newtonsoft.Json nuget package. Then the serialized list can be passed as a parameter and then deserialized again to re-create the original list.
So in your SelectQuestion method you would use this code:
return RedirectToAction("Question",
new {
email = email,
serializedModel = JsonConvert.SerializeObject(fadd.ToList())
});
And in your Question method, you would use this code to deserialize the object.
[HttpGet]
public ActionResult Question(string email, string serializedModel)
{
// Deserialize your model back to a list again here.
List<QuestionClass.Tabelfields> model = JsonConvert.DeserializeObject<List<QuestionClass.Tabelfields>>(serializedModel);
}
Important, this adds the model as a query string parameter to your url, so only do this with really simple small objects, otherwise your url will be too long.
This is probably not even active anymore, but I'll leave how I did it here to maybe help someone else.
I solved this using a simple Redirect instead of a RedirectToAction:
List<int> myList = myListofItems;
var list = HttpUtility.ParseQueryString("");
myList.ForEach(x => list.Add("parameterList", x.ToString()));
return Redirect("/MyPath?" + list);
Then, on your other method:
public ActionResult Action(List<int> parameterList){}
RedirectToAction method Returns an HTTP 302 response to the browser, which causes the browser to make a GET request to the specified action.
You should either keep the data in a temporary storage like TempData / Session . TempData uses Session as the backing storage.
If you want to keep it real Stateless, you should pass an id in the query string and Fetch the List of items in your GET Action. Truly Stateless.
return RedirectToAction("Question", new { email = email,id=model.ID });
and in your GET method
public ActionResult Question(string email,int id)
{
List<QuestionClass.Tabelfields> fadd=repositary.GetTabelFieldsFromID(id);
//Do whatever with this
return View();
}
Assuming repositary.GetTabelFieldsFromID returns a List of TabelFields from the Id
customers is a List<string>.
RedirectToAction("ListCustomers", new { customers = customers });
And when I send the list it contains 4 items, but when I receive it in my controller method it has only one item and it's of type generic list. That seems not be what I want. But how to pass more complex data than strings and integer between controller methods?
You cannot send complex objects when redirecting. When redirecting you are sending a GET request to the target action. When sending a GET request you need to send all information as query string parameters. And this works only with simple scalar properties.
So one way is to persist the instance somewhere on the server before redirecting (in a database for example) and then pass only an id as query string parameter to the target action which will be able to retrieve the object from where it was stored:
int id = Persist(customers);
return RedirectToAction("ListCustomers", new { id = id });
and inside the target action:
public ActionResult ListCustomers(int id)
{
IEnumerable<string> customers = Retrieve(id);
...
}
Another possibility is to pass all the values as query string parameters (be careful there's a limit in the length of a query string which will vary among browsers):
public ActionResult Index()
{
IEnumerable<string> customers = new[] { "cust1", "cust2" };
var values = new RouteValueDictionary(
customers
.Select((customer, index) => new { customer, index })
.ToDictionary(
key => string.Format("[{0}]", key.index),
value => (object)value.customer
)
);
return RedirectToAction("ListCustomers", values);
}
public ActionResult ListCustomers(IEnumerable<string> customers)
{
...
}
Yet another possibility is to use TempData (not recommended):
TempData["customer"] = customers;
return RedirectToAction("ListCustomers");
and then:
public ActionResult ListCustomers()
{
TempData["customers"] as IEnumerable<string>;
...
}