Turn ViewModel into QueryString - asp.net-mvc

I have a ViewModel that I would like to use to populate the QueryString, almost the opposite of the binding that MVC does out of the box. So for the model that looks like this:
public class SearchViewModel
{
public string Keywords { get; set; }
// more properties here
}
I would hope to be able to do something like this:
string querystring = AspMagicMethods.GetQueryStringFromViewModel(searchViewModel);
// querystring == ?keywords=booyah&...
Obviously I could go through each property and create the string myself, but I was wondering if there's anything built into the framework that might be of assistance.

You can use following method of MVC to do so from any controller action.
var myModel = new SearchViewModel{Keywords ="test"};
RedirectToAction("actionName", "controllerName", myModel)

Related

URL Parsing - routing or other?

I am in the process of migrating PHP code to ASP.NET MVC and previously for the register page I would store if the new user had accepted the rules and also was COPPA verified by redirecting from /register to /register&readrules=1&coppa=1. I would then just parse the #readrules and #coppa in the code.
What is the best way to do this in ASP.NET? Thanks
Use query string parameters instead:
/register?readrules=1&coppa=1
This is more standard and you do not need any parsing. Just define a view model to accomodate those values:
public class MyViewModel
{
public int Readrules { get; set; }
public int Coppa { get; set; }
}
and ten have your Register controller action take this view model as parameter:
public ActionResult Register(MyViewModel model)
{
... at this stage model.Readrules and model.Coppa will contain the values passed
as query string parameters tat you could use here
}
The default model binder will automatically bind the values of the readrules and coppa query string parameters to the corresponding properties of the view model that your controller action takes.

How can the MVC View determine which ActionResult passed the model?

Is there anyway in a MVC strongly typed View to find out which ActionResult in the controller passed the Model? I do not want to add extra fields in the Model at this stage or add anything in my querystring? Is it even possible?
Sorry this may be a noob question. Any help is appreciated.
Never mind mumbling about validation of the principles of the MVC Architecture ;)
Place this code in your view:
string action = #ViewContext.Controller.ValueProvider.GetValue("action").RawValue.ToString();
In the view you can acess the Context, then you can retrieve the action/controller from the current request like this:
#{
string controller = RequestContext.RouteData.Values["controller"].ToString();
string action = RequestContext.RouteData.Values["action"].ToString();
}
Then you can use it at the view to make some conditional
#if(action.Equals("some name"))
{
//Do stuff here
}
The Action should tell the View. Instead of adding extra fields to your model you could wrap it in a ViewModel:
public class MyViewModel
{
public MyModel InnerModel {get; set; }
public string ActionName {get; set; }
}
Or use ViewBag:
ViewBag.ActionName = "MyActionName";

asp.net mvc form values display

I'm new to asp.net mvc. Basically i'm from php programmer. In my php file i can display what are all the values coming from html page or form using echo $_POST; or print_r($_POST); or var_dump($_POST). But in asp.net how can i achieve this to check what are all the values are coming from UI Page to controller.
You may take a look at the Request.Form property:
public ActionResult SomeAction()
{
var values = Request.Form;
...
}
You could put a breakpoint and analyze the values. Or simply use a javascript development toolbar in your browser (such as FireBug or Chrome Developer Toolbar) to see exactly what gets sent to the server.
But normally you are not supposed to directly access the raw values. In ASP.NET MVC there's a model binder which could instantiate some model based on the values sent to the server.
For example you could have the following model:
public class MyViewModel
{
public int Age { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
and then have your controller action take this model as parameter:
public ActionResult SomeAction(MyViewModel model)
{
... you could use the model properties here
}
and now you could invoke this controller action either wityh a GET request passing the parameters in the query string (/someaction?age=10&firstname=foo&lastname=bar) or using a POST and sending them in the body.
You can check the raw data via Request.Form.
But this is not he spirit of the ASP.NET MVC. It is preferd that you expect a model into your controller. You have all type safety mapping already done by special module called model binder.
So unless you work on some special case, you just add a model to the controller action:
public ActionResult SomeAction(SomeModel model)
{
//Handle SomeModel data further ...
}
You can create an action which will accept the parameters from the UI page like the following:
[HttpPost]
public ActionResult SomeAction(string param1, int param2)
{
//Now you can access the values here
}
or make an action which will accept the model
public ActionResult SomeAction(SomeModel model)
{
//Access the model here
}

ASP.NET MVC - get list of objects from query string

I'm passed a list of parameters. Such as "Name", "Id", "Type". There will be an many of these in url, like so:
"Name=blah1,Id=231,Type=blah1;Name=blah2,Id=2221,Type=blah1;Name=blah3,Id=45411,Type=blah3;"
I wonder if there is a way to map these query parameters to a List of objects. So, I can create an object:
MyTestObject {Name;Id;Type} and can say in my controller
Index(IList<MyTestObject> params)
params will be filled in with data from query string.
Something that is similar to http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx
I actually followed advice in the article by Mr. Haack I created a class with all of the parameters as public properties. Then I had a view take a list of objects of that type. If the query parameter names follow a certain pattern (prepended by index) then I get a list of my object automatically populated and I don't have to do any manual parsing at all. This is the simplest solution for me.
Example:
query param object:
public class QueryParams
{
public string Id,
public string Name,
public string Type
}
in controller method:
public ActionResult Index(IList<QueryParams> queryData)
then I make sure that query string is formated in the following way(prepended by index):
http://localhost/myapp/?[0].id=123&[0].Name=blah&[0].Type=Person&[1].Id=345&[1].Name=example&[1].Type=Stuff
In my controller, queryData list parameter will contain two objects populated with correct data.
You can you a values provider, and it will populate values from the querystring into a single object. This is what you would do if you're not going to create a View Model.
Transform the QueryString into a FormCollection via:
var GetCollection = new FormCollection( Request.QueryString );
You could create a custom model binder, that works off the Request.QueryString collection, rather than the regular FormCollection.
E.g:
public class MyTestObjectModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var qs = controllerContext.HttpContext.Request.QueryString;
return new MyTestObject
{
Name = qs["Name"],
Id = qs["Id"],
// etc, etc
};
}
}
Then setup your [HttpGet] action accordingly:
[HttpGet]
public ActionResult Index([ModelBinder(typeof(MyTestObjectModelBinder))]MyTestObject m) {
}
You could also register it globally if you like, e.g on Application_Start() :
ModelBinders.Binders.Add(typeof(MyTestObject), new MyTestObjectModelBinder());
Then you just need the model on your action:
[HttpGet]
public ActionResult Index(MyTestObject m) {
}
Having said all of this, if you've got this many parameters, one must ask where do these parameters come from? Most likely a form on another page.
In which case, this should be a [HttpPost] action, with the parameters in the form collection, then the regular MVC model binding will take care of the above code for you.
Yes, ASP.NET MVC could automatically bind collections to action params, but you need to pass your params as a from values, moreover, it is looks like to many params you going pass in query string. Have look at this one http://weblogs.asp.net/nmarun/archive/2010/03/13/asp-net-mvc-2-model-binding-for-a-collection.aspx
Basically what you need to do:
1) Create your class which would contain your params
public class MyParam
{
public int Id {get; set;}
public string Name {get; set;}
//do all the rest
}
2) Create model which you would pass to your view
public class MyViewModel
{
IList<MyParam> MyParams {get; set;}
}
3) Create your collection in your [HttpGet] action and pass that to your view:
[HttpGet]
public virtual ActionResult Index()
{
MyViewModel model = new MyViewModel();
model.MyParams = CreateMyParamsCollection();
return View(model);
}
4) Iterate your collection in the view
#model MyViewModel
#{int index = 0;}
#foreach (MyParam detail in Model.MyParams)
{
#Html.TextBox("MyParams[" + index.ToString() + "].Id", detail.Id)
#Html.TextBox("MyParams[" + index.ToString() + "].Name", detail.Name)
index++;
}
5) Than on your [HttpPost] action you may catch your params in collection
[HttpPost]
public virtual ActionResult Index(MyViewModel model)
or
[HttpPost]
public virtual ActionResult Index(IList<MyParam> model)
P.S
Moreover, if you want to get all your form params in controller you may simple go like that:
[HttpPost]
public virtual ActionResult Index(FormCollection form)
On a related note, I was looking for a way to enumerate through the QueryString name-value collection, and this is what I came up with:
var qry =HttpContext.Request.QueryString;
if (qry.HasKeys())
{
foreach (var key in qry)
{
if(key != null)
var str= String.Format("Key:{0}, value:{1} ", key, qry.Get(key.ToString()));
}
}
This code will give you all the names and their values in the QueryString.

Using named parameters as controller input versus FormCollection

I'm new to ASP.NET MVC so this could have an obvious answer. Right now I have a form in my view with a lot of input controls, so I have an action that looks like this:
public ActionResult MyAction(string formItemOne, int? formItemTwo, etc...)
It has like a dozen parameters, which is pretty ugly. I'm trying to change it to this:
public ActionResult MyAction(FormCollection formItems)
and then parse the items dynamically. But when I change to a FormCollection, the form items no longer "automagically" remember their values through postbacks. Why would changing to a FormCollection change this behavior? Anything simple I can do to get it working automagically again?
Thanks for the help,
~ Justin
Another solution is to use models instead of manipulating the raw values. Like this:
class MyModel
{
public string ItemOne { get; set; }
public int? ItemTwo { get; set; }
}
Then use this code:
public ActionResult MyAction(MyModel model)
{
// Do things with model.
return this.View(model);
}
In your view:
<%# Page Inherits="System.Web.Mvc.ViewPage<MyModel>" %>
<%= Html.TextBox("ItemOne", Model.ItemOne) %>
<%= Html.TextBox("ItemTwo", Model.ItemTwo) %>
To replace your big list of parameters with a single one, use a view model. If after the POST you return this model to your view, then your view will remember the values posted.
A view model is simply an class with your action parameters as public properties. For example, you could do something like this, replacing:
public ActionResult MyAction(string formItemOne, int? formItemTwo, etc...)
with
public ActionResult MyAction(FormItems formItems)
{
//your code...
return View(formItems);
}
where FormItems is
public class FormItems
{
public property string formItemOne {get; set;}
public property int? formItemTwo {get; set;}
}
You may see a complete example in Stephen Walter's post ASP.NET MVC Tip #50 – Create View Models.
Maybe because they aren't magically inserted into the ModelState dictionary anymore. Try inserting them there.
If you use UpdateModel() or TryUpdateModel() I think the values are gonna be persisted.

Resources