In my MVC app the controller gets the data (model) from an external API (so there is no model class being used) and passes that to the view. The data (model) has a container in which there are several objects with several fields (string values). One view iterates over each object and calls another view to draw each of them. This view iterates over the fields (string values) and draws them.
Here's where it gets tricky for me. Sometimes I want to do some special formatting on the fields (string values). I could write 20 lines of code for the formatting but then I would have to do that for each and every field and that would just be silly and oh so ugly. Instead I would like to take the field (string value), pass it to a method and get another string value back. And then do that for every field.
So, here's my question:
How do I call a method from a view?
I realize that I may be asking the wrong question here. The answer is probably that I don't, and that I should use a local model and deserialize the object that I get from the external API to my local model and then, in my local model, do the "special formatting" before I pass it to the view. But I'm hoping there is some way I can call a method from a view instead. Mostly because it seems like a lot of overhead to convert the custom object I get from the API, which in turns contains a lot of other custom objects, into local custom objects that I build. And also, I'm not sure what the best way of doing that would be.
Disclaimer: I'm aware of the similar thread "ASP.NET MVC: calling a controller method from view" (ASP.NET MVC: calling a controller method from view) but I don't see how that answers my question.
This is how you call an instance method on the Controller:
#{
((HomeController)this.ViewContext.Controller).Method1();
}
This is how you call a static method in any class
#{
SomeClass.Method();
}
This will work assuming the method is public and visible to the view.
Building on Amine's answer, create a helper like:
public static class HtmlHelperExtensions
{
public static MvcHtmlString CurrencyFormat(this HtmlHelper helper, string value)
{
var result = string.Format("{0:C2}", value);
return new MvcHtmlString(result);
}
}
in your view: use #Html.CurrencyFormat(model.value)
If you are doing simple formating like Standard Numeric Formats, then simple use string.Format() in your view like in the helper example above:
#string.Format("{0:C2}", model.value)
You can implement a static formatting method or an HTML helper, then use this syntax:
#using class_of_method_namespace
...
// HTML page here
#className.MethodName()
or in case of a HTML Helper:
#Html.MethodName()
Controller not supposed to be called from view. That's the whole idea of MVC - clear separation of concerns.
If you need to call controller from View - you are doing something wrong. Time for refactoring.
why You don't use Ajax to
its simple and does not require page refresh and has success and error callbacks
take look at my samlpe
<a id="ResendVerificationCode" >#Resource_en.ResendVerificationCode</a>
and in JQuery
$("#ResendVerificationCode").on("click", function() {
getUserbyPhoneIfNotRegisterd($("#phone").val());
});
and this is my ajax which call my controller and my controller and return object from database
function getUserbyPhoneIfNotRegisterd(userphone) {
$.ajax({
type: "GET",
dataType: "Json",
url: '#Url.Action("GetUserByPhone", "User")' + '?phone=' + userphone,
async: false,
success: function(data) {
if (data == null || data.data == null) {
ErrorMessage("", "#Resource_en.YourPhoneDoesNotExistInOurDatabase");
} else {
user = data[Object.keys(data)[0]];
AddVereCode(user.ID);// anather Ajax call
SuccessMessage("Done", "#Resource_en.VerificationCodeSentSuccessfully", "Done");
}
},
error: function() {
ErrorMessage("", '#Resource_en.ErrorOccourd');
}
});
}
You should create custom helper for just changing string format except using controller call.
I tried lashrah's answer and it worked after changing syntax a little bit.
this is what worked for me:
#(
((HomeController)this.ViewContext.Controller).Method1();
)
You should not call a controller from the view.
Add a property to your view model, set it in the controller, and use it in the view.
Here is an example:
MyViewModel.cs:
public class MyViewModel
{ ...
public bool ShowAdmin { get; set; }
}
MyController.cs:
public ViewResult GetAdminMenu()
{
MyViewModelmodel = new MyViewModel();
model.ShowAdmin = userHasPermission("Admin");
return View(model);
}
MyView.cshtml:
#model MyProj.ViewModels.MyViewModel
#if (#Model.ShowAdmin)
{
<!-- admin links here-->
}
..\Views\Shared\ _Layout.cshtml:
#using MyProj.ViewModels.Common;
....
<div>
#Html.Action("GetAdminMenu", "Layout")
</div>
Related
I'm using MVC3 razor, and I'm trying to pass an object to a partial view, and it's not working.
This works fine without sending the object model to the partial view:
Html.RenderAction("Index", "ViewName");
Trying this doesn't sent the model object, i'm getting nulls instead (the object has data, and the view expects it):'
Html.RenderAction("Index", "ViewName", objectModel);
Is this even possible using RenderAction?
Thanks!
Edit: I found the error, there was an error with the controller's action that didn't pick up the sent object. Thanks for all your help!
You can actually pass an object to a controller method using Action. This can be done on any avaialble view, for instance I have one in a shared library that gets built to project bin folders that reference my shared project (properties - Copy if newer on the view file, in Visual Studio). It is done like so:
Controller:
public class GroovyController : Controller
{
public ActionResult MyTestView(MyModel m)
{
var viewPath = #"~\bin\CommonViews\MyTestView";
return View(viewPath, m);
}
}
MVC page (using Razor syntax):
#Html.Action("MyTestView", "Groovy", new { m = Model })
or using RenderAction method:
#{ Html.RenderAction("MyTestAction", "MyTestController", new { area = "area", m = Model }); }
Note: in the #Html.Action(), the Model object must be of type MyModel and that 3rd parameter must be set to the controller variable name, of which mine is MyModel m. The m is what you must assign to, so I do m = Model.
say you want to pass foo as model, make it first
public class Foo {
public string Name { get; set; }
public int Age { get; set; }
}
now make an ActionResult
public ActionResult FooBar(Foo _foo){
return PartialView(_foo);
}
call it
#Html.RenderAction("FooBar", "Controller", new { Name = "John", Age=20 });
Usually if I have a model already available it makes more sense to use Html.Partial than trying to render an action.
#Html.Partial("Foo", Model.FooModel)
Where Foo.cshtml is a view file (perhaps in your Shared folder) strongly typed with with #model FooProject.Models.FooModel or whatever your model is called. This can be as complex a model as you need it to be. Model is your page's main model into which you must set FooModel - or just omit this parameter if the Foo view uses the same model as the parent page.
RenderAction is generally better when you have just simple parameters, because you're just simulating a request to a regular action which has routing/query string parameters - and then dumping that response into your page. It works well if you need to put something in a Layout that isn't available in your page's model such as an element in a side bar.
I am new to MVC and Web Api, and getting stuck.
Please Note: I am using ApiControllers, not Controllers!
Situation
I have two partial views. The first has drop down lists and a submit button. The second is just a confirmation view showing what the user selected after user submits. On clicking submit, I want to send a string (containing the user's combined selections) to the second partial view and update it.
Question
When I press submit on the first partial view, I want to send a string to the second partial view and update the second partial view. How can I do this? The sending of the string can be indirect, of course, like view to controller then back to view. I just want to know at least one way.
Again, note that I am using Web Api Controllers, NOT Controllers. Most people use normal Controllers, which doesn't apply to me. They are different.
Things I tried / What I believe I cannot do from other StackOverflow answers:
I cannot use a Controller method to return a Partial View, like in this very similarly asked question Same question but not with ApiControllers.
I cannot store any data into a class, so I cannot strongly type a view with #model ExampleClass to access stored contents with #Model.ExampleProperty.
Since I cannot store data into a class or return a model from a controller method like View(model), I also could not use Html.DropDownListFor(model => model.SelectedValue) to store the SelectedValue into my model and access it in the other partial view. Instead to populate my drop down lists, I manually added a div, called a GET method that returned a list, and populated the lists by appending to them.
So, what exactly CAN I do? I also tried ViewData, but the stored data would not last after a Controller method finished. I am out of ideas. I hope I am mistaken about something and missed a method, because it feels it should not be this hard. If you could even briefly describe the flow of how I would transfer a string and/or update the second partial view after pressing submit, that would be greatly appreciated!
Thanks so much in advance!
Model class
public class Vehicle
{
public class Make
{
public int MakeId { get; set; }
public string MakeName { get; set; }
}
public class Model
{
public int ModelId { get; set; }
public string ModelName { get; set; }
}
}
ApiController class. The ViewData seems to not save its contents. I wanted to store the user's selections into ViewData with the first POST method, and GET the selections with the second method, but the contents of ViewData have become null already.
public class VehicleController : ApiController
{
public ViewDataDictionary ViewData = new ViewDataDictionary();
[HttpPost]
public void StoreMakeAndModel(string user_selections){
ViewData["message"] = user_selections;
}
[HttpGet]
public string ConfirmationMessage(){
ViewData["message"] = "You selected the " + ViewData["message"].ToString();
return ViewData["message"].ToString();
}
//This returns a list to populate a drop down list
[HttpGet]
public IEnumerable<Vehicle.Make> Makes(){
//This function reads from xml and returns List<Vehicle.Make>
...
return makesList;
}
//This returns a list to populate a drop down list
[HttpGet]
public IEnumerable<Vehicle.Model> Models(int id){
//This function reads from xml the car models that match the make id
...
return modelsList;
}
}
First partial view It has 2 drop down lists and submit button. There is a hidden div that shows once the form submits that renders the second partial view. I hoped that it would load only when it is shown so that I can use $(document).ready(function()) to display my string there, but it loads when the main page loads even though it's hidden. So I don't know how to update it with the string after the first partial view submits.
<select required id="makes_DDL" name="makes_DDL"></select>
<select required id="models_DDL" name="models_DDL"></select>
<input type="submit" id="submit_button" value="Submit Form" onclick="formSubmit()" />
<div id="thank_you_div" style="display:none;">
#Html.Partial("_ThankYou");
</div>
function formSubmit() {
//Combines the make and model into one string, Ex: Chevrolet Malibu
var parameter = $("#makes_DDL").children(":selected").text() + " "
+ $("#models_DDL").children(":selected").text();
var uri = "api/vehicle/storemakeandmodel/" + parameter;
$.ajax({
url: uri,
type: "post",
updatetargetid: "thank_you_div",
success: function (data) {
$("#thank_you_div").show();
},
});
}
My list population looks like this; this is my first list. I could not get #Html.DropDownListFor to work because I could not store anything since I cannot return something like View(model) from a controller method.
$(document).ready(function () {
$.getJSON("api/vehicle/makes", function (makes) {
$("#makes_DDL").append("<option value= ''>Select a make</option>");
$.each(makes, function (id, make) {
$("#makes_DDL").append("<option value=" + make.MakeId + ">" + make.MakeName + "</option>");
});
});
});
Second partial view It tries to get the stored message in ViewData, but it is already gone and GETS null.
<div id="thank_you_div">Thank you!</div>
<script type="text/javascript">
$(document).ready(function () {
alert("Thank You Partial View ready!");
$.ajax({
url: "api/vehicle/confirmationmessage",
type: "get",
updatetargetid: "thank_you_div",
success: function (message) {
$("#thank_you_div").html(message)
}
});
})
</script>
Take a look at your ApiController action methods.
[HttpPost]
public void StoreMakeAndModel(string user_selections)
{
ViewData["message"] = user_selections;
}
[HttpGet]
public string ConfirmationMessage()
{
ViewData["message"] = "You selected the " + ViewData["message"].ToString();
return ViewData["message"].ToString();
}
Looks like you are trying to store data to ViewData when the first method is called and read it in the second method when you make your second ajax call. But that will not work! Because http is stateless. Your second call has no idea what your first call did. You cannot store data in ViewData to access between multiple http requests. It does not make sense to use ViewData in an api controller at all. Api controller endpoints should be purely to return data.
In your case, what you should be doing is, simply have your first method return the string message you want. In the success handler of the first ajax call,you will get this string (Response from the api method) in the success call back. You can use this to update the DOM as needed.
There is no need to have the partial view as well. All you need is a container div element to show the response.
<select required id="makes_DDL" name="makes_DDL"></select>
<select required id="models_DDL" name="models_DDL"></select>
<input type="submit" id="submit_button" value="Submit Form" onclick="formSubmit()" />
<div id="thank_you_div" style="display:none;"></div>
Now in your first ajax call's success callback, update the DOM with the response coming back.
Also $.ajax does not have a setting property called updatetargetid !
function formSubmit() {
//Combines the make and model into one string, Ex: Chevrolet Malibu
var parameter = $("#makes_DDL").children(":selected").text() + " "
+ $("#models_DDL").children(":selected").text();
var uri = "api/vehicle/?user_selections=" + parameter;
$.ajax({
url: uri,
type: "post"
}).done(function(res) {
$("#thank_you_div").html(res).show();
}).fail(function(x, v, e) {
console.log(e);
});
}
Assuming your api controller method returns the string you want
[HttpPost]
public string StoreMakeAndModel(string user_selections)
{
return "You selected the "+user_selections;
}
I am fairly new to MVC and had a question about a form I am creating. The page has a form at the top and a grid at the bottom. As people enter data into the form and click the button, the form data is added to the grid below.
My plan is to use a BeginForm and send the form to an HttpPost controller method for processing and then bounce back to the view. Currently, I am using this for the form on the view:
#using (Html.BeginForm("AddRefund", "Refund", FormMethod.Post))
In the controller, I have this:
[HttpPost]
public ActionResult AddRefund(RefundModel refund)
{
if (ModelState.IsValid)
{
(etc...)
My problem is that the "refund" object in controller always arrives from the view empty. From my research, it seems that the model reference in the controller is just there to provide model structure, and NOT to receive the actual model from the view. I don't understand why this is, however, as it would seem very valuable to be able to send a populated viewmodel from the view to a controller.
Also, how would you guys handle the code for this problem? How would you collect all of these form submissions from the user, present them to the user in the grid below the form, and then ultimately submit the page and insert all of the items in the grid into the database?
edit: here is my view
#model RefundsProject.Models.RefundModel
#using (Html.BeginForm("AddRefund", "Refund", FormMethod.Post))
{
(all of the form elements are here)
<input id="button-add" type="submit" value=" Add Refund to List " />
}
Eventually, there will be another button at the very bottom of the view that will submit all of the items the user entered into the grid to the database.
From my research, it seems that the model reference in the controller is just there to provide model structure, and NOT to receive the actual model from the view.
This is completely the opposite of the way ASP.Net MVC was designed. ASP.Net comes with default ModelBinders that are used to Bind data from a Form, Querystring, Ajax (Json and XML) to a strongly typed object for a Controller Method.
My problem is that the "refund" object in controller always arrives from the view empty.
This is most likely due to a lack of knowledge or a misunderstand of how model binders work.
Also, how would you guys handle the code for this problem?
I would Ajax Post the RefundModel back to the controller to validate the refund. If it is valid, then dynamically create fields in the form that will eventually model bind back to an IEnumerable/List on a new method that will then verify all the refunds, one at a time (to validate the data again).
Here is an Extremely broken down example (probably needs some work, but the important parts are there):
Classes:
public class AddRefundsViewModel
{
public RefundModel Refund { get; set; }
}
public class RefundModel
{
public string Reason { get; set; }
public Decimal Amount { get; set; }
}
Methods:
public ActionResult AddRefunds()
{
var model = new AddRefundsViewModel()
model.Refund = new RefundModel();
return this.View(model);
}
[HttpPost]
public ActionResult ValidateRefund(AddRefundsViewModel model)
{
var result = new { isValid = modelState.IsValid };
return this.Json(result);
}
[HttpPost]
public ActionResult ValidateRefunds(IEnumerable<RefundModel> model)
{
var isRefundsValid = true;
foreach (var refund in model)
{
isRefundsValid = TryValidateModel(refund);
if (!isRefundsValid )
break;
}
if (isRefundsValid)
{
}
else
{
// either someone hacked the form or
// logic for refunds changed.
}
}
Views:
#model AddRefundsViewModel
// assuming RefundController
#using (Html.BeginForm("Refund", "ValidateRefunds", FormMethod.Post))
{
#html.EditFor(m => m.Refund.Reason)
#html.EditFor(m => m.Refund.Amount)
<input type="button" id="addRefundButton" name="addRefundButton" value="add"/>
<input type="submit" id="submitRefundButton" name="submitRefundButton" value="submit all"/>
}
<!-- jquery -->
$(document).ready(function()
{
$('#addRefundButton').on('click', function()
{
$.ajax({
url: '/Refund/ValidateRefund',
data: $("addRefundForm").serialize(),
success: function(result)
{
if (result.isValid)
{
// create new hidden imput elements, and grid
$("addRefundForm")[0].reset();
}
else
{
// Refund isn't valid
}
}
});
});
});
From my research, it seems that the model reference in the controller is just there to provide model structure, and NOT to receive the actual model from the view. I don't understand why this is, however, as it would seem very valuable to be able to send a populated viewmodel from the view to a controller.
Your a bit wrong. There is a difference between ViewModel and Domain Model. View Model is a class that you use to process the logic between views and your domain (business).
Then there is Domain Model (in .net) this is usually some data container objects (POCO). This is anemic. Based on DDD there is a little difference.
So what is the best practive?
It is always good to use a ViewModel object to transfer data between your views and controller.
Then in controller you can use a mapper (automapper or valueinjecter) to transform them.
Now you have your domain object that you can process.
Using ViewModels to pass data both up and down between controllers and views is completely acceptable.
To help with your model coming up empty issue, inputs, such as <input id="FirstName" type="text" /> need to have name attributes for the MVC model binder to map what you posted into your RefundModel object. In your View code you shared, you only showed a submit button, so it is unclear if your other elements you expect to get mapped have names or not.
To fix my above example of an input tag, you would do <input id="FirstName" name="FirstName" type="text" /> or use a Razor helper: #Html.TextBoxFor(m => m.FirstName)
Without customization, can I do something like this in MVC 3?
[HttpGet]
public ViewResult MyAction(ViewModel model)
{
// Do stuff
return View("ViewName", model);
}
The reason I am doing this is to pass data between different pages as part of a work flow. (I.e. when user fnishes what's needed in step 1, pass the form data to step 2...)
It will work as long as you have the same parameter Name as of the Property name of your Model class
Assuming your class is like this
public class ViewModel
{
public string Name { set;get;}
public string Loc{ set;get;}
}
You can do a Get request like this
MyAction?Name=jon&Loc=America
Shyju's answer only works if the members of class in the endpoint's method signature contains only scalar properties. But what if you have nested classes? Let's assume that your ViewModel class looks like this:
public class ViewModel
{
public string Name { get; set; }
public string Title { get; set; }
public Address MyAddress { get; set; }
}
And the Address class looks like this:
public class Address
{
public string Line1 { get; set; }
public string Line2 { get; set; }
}
Now let's say the GET request was done via AJAX and you did something like this in JavaScript:
var address = {
Line1: "123 Nowhere St.",
Line2: "Apt. B5"
}
var getRequestData = {
Name: "Joe",
Title: "Manager",
MyAddress: address
}
var uriString = $.param(getRequestData); //the parameters for the GET request
$.get("/ViewResult?" + uriString, function (data) { /*callback function*/ });
Even though the shape of your address object in JavaScript perfectly matches the C# Address class in the endpoint's method signature, the Line1 and Line2 sub-properties will NOT bind. Their values will come through as null.
There are two workarounds to this.
Workaround 1:
The first is to use dot notation when naming the parameters in the GET request instead of nested JavaScript objects. Using this method, the GET request data in AJAX would look like this:
var getRequestData = {
Name: "Joe",
Title: "Manager",
MyAddress.Line1: "123 Nowhere St.",
MyAddress.Line2: "Apt. B5"
}
MVC model binding will know how to do this, as long as all your property names all match up (they are case-sensitive, so be careful).
If you're not using AJAX, but just a plain HTML form submit, it's even easier. Just name the input elements with that same dot notation. Razor syntax makes this really easy with helper methods like TextBoxFor(), but here's an example in plain HTML:
<form method="get" action="/ViewResult">
<input type="text" name="Name" />
<input type="text" name="Title" />
<input type="text" name="MyAddress.Line1" />
<input type="text" name="MyAddress.Line2" />
<button type="submit">Submit GET request</button>
</form>
Workaround 2:
The other way around this is to simply use a POST request instead of a GET. Beware that it's technically bad practice to perform a POST request without the intent of actually changing some data on the server side, but it is an option.
You can do it; it will automatically bind any values in the query string to properties with matching names.
That said, it's not something that's generally done; it's the [HttpPost] method where you see the model binding performed, as the interfaces for the two actions need to be different somehow. You can solve that by posting back to a different action name, but you may still trigger model validation errors on the (partial) load of the model, which would be really confusing to a user.
For Web API 2:
[HttpGet]
public ActionResult Get([FromUri]ViewModel model)
{
// Do stuff
return View("ViewName", model);
}
You can post a form to a get by setting the PostMethod attribute to get. If the form's input fields match any of the accepting ViewModel then they will be filled. These matches are determined by the name field in an input (<input name="MatchedField"> -> public string MatchedField { get; set; }).
What you should do is pass the form from a post, and then redirect to the get from the post action. This pattern is best practice and is known as the Post-Redirect-Get pattern.
I would advise against this approach. Best solution to just use POST, because if you use GET, once you click back from step 3 to step 2 and the browser cache is not available, you will perform actions on an old version of the ViewModel. Is there a particular reason why you want to use GET?
I can not suggest to use QueryString to pass values.
You can use one of below:
This code will render a partial view with the given model.Be sure you add model to your view. And your view should be placed in Shared folder
public ActionResult myaction(ViewModel model)
{
return PartialView("anotherView", model);
}
Another way to do almost the same thing:
public ActionResult myaction(ViewModel model)
{
return View("someAnotherView", model);
}
if your view is not in the same controller , use the path for view name like "../Controller/viewName"
There is also a different approach which can be done by using TempData:
public ActionResult myaction(ViewModel model)
{
TempData["model"] = model;
return RedirectToAction("someAnotherView");
}
but you should reach your data in the view with the code as shown below:
#{
ViewModel model=(ViewModel)TempData["model"];
}
Hope one of above helps..
Regards
Is it possible from a Controller to show a view, and then dependant on what that user selects in dropDownList - render another different view back in the original calling controller? Kind of a "daisy-chaining" effect.
The thinking behind this - is a user selecting a vehicle type - (associated with an ID number) in a view, back in the Controller dependant on what was chosen will render another view immediately displaying HTML according to the vehicle type they chose e.g. an HTML page for car or a boat or aeroplane etc...
If this is possbile can someone point me to a code examaple?
Actual Database Model below - but it is for documents, not vehicles!
check the method paremetares of your action method and return different views baed on that . Something like this.
public ActionResult GetInfo(string id,string vehicleTypId)
{
if(String.IsNullOrEmpty(vehicleTypeId))
{
var vehicle=GetVehicleType(vehicleTypId);
return View("ShowSpecificVehicle",vehicle) ;
}
var genericVehicle=GetVehicle(id);
return View(genericVehicle);
}
EDIT : Saying so, I seriously think you should keep those in 2 seperate Action methods. That makes your code clean and better readable. You may move the common functionality to a function and call if from bothe the action methods id needed. So i would do it in this way
Assuming you have a ViewModel for the first page( displays all vehicletypes)
public class VehicleTypesViewModel
{
//other relevant properties
public IEnumerable Types { set;get;}
public int SelectedTypeId { set;get;}
}
Your GET request for the initial view will be handled by this action result.It gets all the Vehicle types and return that to your view in the ViewModels Types property.
public ActionResult VehicleTypes()
{
VehicleTypesViewModel objVM=new VehicleTypesViewModel();
objVM.Types=dbContext.VehicleTypes.ToList();
return View(objVM);
}
and in your View called VehicleTypes.cshtml,
#model VehicleTypesViewModel
#using(Html.BeginForm())
{
#Html.DropDownListFor(Model.SelectedTypeId,new SelectList(Model.Types,"Text",Value"),"Select")
<input type="submit" value="Go" />
}
Another Action method to handle the form post. You have the selected type id here and you can get the specific details here and return a different view
[HttpPost]
public ActionResult VehicleTypes(VehicleTypesViewModel model)
{
// you have the selected Id in model.SelectedTypeId property
var specificVehicle=dbContext.Vehicles.Where(x=>x.TypeId=model.SelectedTypeId);
return View("SpecificDetails",specificVehicle);
}
Alternatively you can do a Get request for the specific vehicle using RedirecToAction method. I would prefer this approach as it sticks with the PRG pattern.
[HttpPost]
public ActionResult VehicleTypes(VehicleTypesViewModel model)
{
int typeId=model.SelectedTypeId;
return RedirectToAction("GetVehicle",new {#id=typeId});
}
public ActionResult GetVehicle(int id)
{
var specificVehicle=dbContext.Vehicles.Where(x=>x.TypeIdid);
return View(specificVehicle);
}
With Javascript : You can do a get call to the new view from your javascript also. without the HTTPpost to controller. You should add some javascript in your initial view for that
#model VehicleTypesViewModel
//Include jQuery library reference here
#Html.DropDownListFor(Model.SelectedTypeId,new SelectList(Model.Types,"Text",Value"),"Select")
<script type="text/javascript">
$(function(){
$("#SelectedTypeId").change(){
window.location.href="#Url.Action("GetVehicle","Yourcontroller")"+"/"+$(this).attr("id");
});
});
</script>
I think to get a better user experience create a partial view, and load that partial view in a div in the same page via an ajax call.
public ActionResult GetVehicalInfo(string id, string vehicleType)
{
var vehicle = GetVehicleType(id, vehicleTypId);
return PartialView("vehicle);
}