Pass parameter value from url back to view module - asp.net-mvc

I am trying to pass a parameter value from my url back to the view model. Here is the url: StudentDetails/MarkingToolView/1?studentId=1
I am trying to get the first parameter of 1 (after MarkingToolview/) so I can post it back to my database
my viewModel:
public class MarkingVM
{
public int? ModuleID { get; set; }
}
my view:
#Html.HiddenFor(m => m.ModuleID, new { id = ??? })
What is the best way to do this?

I think you are asking how to get the url parameter into your view perhaps? Something like the following will populate your view model.
Controller
public action MarkingToolView(int studentId)
{
MarkingVM vm = new MarkingVM(); //or however that is initialized.
vm.ModuleID = studentId;
return View(vm);
}

Related

ASP.NET MVC Passing ID from Controller to View

Hi I am trying to pass an ID from the URL from a controller to a view. I am also passing a viewmodel that contains two models that have data from a database. Is there another way of doing this? The routemap has been set to send an ID.
The URL would be http://localhost:55147/Home/ViewProject/8 which obviously 8 is the ID of the project, but it does not seem to get this. I am passing the ID to the ViewProject controller function by URL.Action which has the ID passed through the parameter on another page.
Here is my controller:
public ActionResult ViewProject( int? id )
{
if( id == null )
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
BextecODBEntities DB = new BextecODBEntities();
var mymodel = new Multipledata();
mymodel.projectss = DB.Projects.ToList();
mymodel.projectnotess = DB.ProjectNotes.ToList();
return View("ViewProject", mymodel);
}
Here is my View:
#foreach(var item in Model.projectss)
{
if( item.ID.ToString() == Html.ViewContext.RouteData.Values["id"].ToString() )
{
#Html.DisplayText("You have clicked on Project ID:" + item.ID.ToString())
}
}
My multiple data model contains:
public IEnumerable<Projects> projectss { get; set; }
public IEnumerable<ProjectNotes> projectnotess { get; set; }
Instead of sending a list of Projects I have sent the specific Project data I have defined in the database model using the Project.Find(id) passed through the parameter like you have said

Asp.Net MVC 5 How to send ViewBag to Partial View

I have a _LoginPartial View and want to send data to it by ViewBag, but the Controller that I'am sending data from, doesn't have a View.
public PartialViewResult Index()
{
ViewBag.sth = // some data
return PartialView("~/Views/Shared/_LoginPartial.cshtml");
}
This code didn't work for me.
It seems you're expecting this Index action to be called when you do: #Html.Partial('_LoginPartial'). That will never happen. Partial just runs the partial view through Razor with the current view's context and spits out the generated HTML.
If you need additional information for your partial, you can specify a custom ViewDataDictionary:
#Html.Partial("_LoginPartial", new ViewDataDictionary { Foo = "Bar" });
Which you can then access inside the partial via:
ViewData["Foo"]
You can also use child actions, which is generally preferable if working with a partial view that doesn't need the context of the main view. _LoginPartial seems like a good candidate, although I'm not sure how exactly you're using it. Ironically, though, the _LoginPartial view that comes with a default MVC project with individual auth uses child actions.
Basically, the code you have would already work, you would just need to change how you reference it by using Html.Action instead of Html.Partial:
#Html.Action("Index")
Notice that you're calling the action here and now the view.
You can always pass data directly to the partial view.
public PartialViewResult Index()
{
var data = // some data
return PartialView("~/Views/Shared/_LoginPartial.cshtml", data);
}
Pass multiple pieces of data
public class MyModel
{
public int Prop1 { get; set; }
public int Prop2 { get; set; }
}
public PartialViewResult Index()
{
var data = new MyModel(){ Prop1 = 5, Prop2 = 10 };
return PartialView("~/Views/Shared/_LoginPartial.cshtml", data);
}
I passed viewBag data to my partial view like below, and I converted that viewBag data object to JSON in my partial view by using #Html.Raw(Json.Encode(ViewBag.Part));
my code sample is given below.
public async Task<ActionResult> GetJobCreationPartialView(int id)
{
try
{
var client = new ApiClient<ServiceRepairInspectionViewModel>("ServiceRepairInspection/GetById");
var resultdata = await client.Find(id);
var client2 = new ApiClient<PartViewModel>("Part/GetActive");
var partData = await client2.FindAll();
var list = partData as List<PartViewModel> ?? partData.ToList();
ViewBag.Part = list.Select(x => new SelectListItem() {Text = x.PartName, Value = x.Id.ToString()});
return PartialView("_CreateJobCardView" ,resultdata);
}
catch (Exception)
{
throw;
}
}
Here i have passed both model and viewBag .
First off, the code in your question does not run. When you do #Html.Partial("_SomeView") the Index() method you have there does not run. All #Html.Partial("_SomeView") does is render _SomeView.cshtml in your current view using the current view's ViewContext.
In order to get this to work you need a bit of functionality that's common to all the controllers in your project. You have two options: extension method for ControllerBase or a BaseController that all the controllers in your project inherit from.
Extension method:
Helper:
public static class ControllerExtensions
{
public static string GetCommonStuff(this ControllerBase ctrl)
{
// do stuff you need here
}
}
View:
#ViewContext.Controller.GetCommonStuff()
BaseController
Controller:
public class BaseController : Controller
{
public string GetCommonStuff()
{
// do stuff you need here
}
}
Other controllers:
public class SomeController : BaseController
...
...
View:
#((ViewContext.Controller as BaseController).GetCommonStuff())

mvc pass tuple data as parameter

I have a tuble like this as model.
#model Tuple<Urun,List<UrunKatagori>>
inside the view I need to pass those data to controler.
here is the my button.
Html.X().Button().Text("Guncelle").Icon(Icon.PageSave)
.DirectEvents(de =>
{
de.Click.Url = "Urunler/Guncelle";
de.Click.ExtraParams.Add(new Parameter { Name = "Urun", Value ="Model.Item1", Mode = ParameterMode.Raw });//Iguess here is wrong
})
and my controller
[HttpPost]
public ActionResult Guncelle (Urun Urun){
Urun_BLL urun_bll = new Urun_BLL();
// urun_bll.Update(mdl);
X.Msg.Notify(new NotificationConfig
{
Icon = Icon.Accept,
Title = "Working",
Html =Urun.Ad.ToString()//I need to get data here
}).Show();
return this.Direct();
}
I strongly suggest that you create a viewmodel class, rather then passing a Tuple e.g.
public class GuncelleViewModel
{
public Urun Urun { get ;set; }
public List<UrunKatagori>> UrunKatagori { get; set; }
}
Then you can pass that to the view like so:
[HttpPost]
public ActionResult Guncelle (Urun Urun)
{
Urun_BLL urun_bll = new Urun_BLL();
// urun_bll.Update(mdl);
X.Msg.Notify(new NotificationConfig
{
Icon = Icon.Accept,
Title = "Working",
Html =Urun.Ad.ToString()//I need to get data here
}).Show();
var viewModel = new GuncelleViewModel()
viewModel.Urun = Urun;
viewModel.UrunKatagori = // TODO - However you get the categories.
return View(viewModel);
// this.Direct(); What does this.Direct() do? Replace it with calling the view instead, much cleaner.
}
In the view, use the following model
#model GuncelleViewModel
Useing a viewmodel class, which is associated one-to-one with a view file (*.cshtml), is a very good practise. It can help keep your design clean and more flexible, rather then passing specific data types, such as Tuple.

ASP.NET MVC - Enum not being sent to Controller

I have a DropDropListFor that looks like this:
using (Ajax.BeginForm("FilterListingsWorkflow", "Listing",
new {
categoryguid = Model.SelectedCategoryGuid,
workflowstatus = Model.SelectedWorkflowStatus,
entityName = Model.EntityName,
},
new AjaxOptions {
HttpMethod = "POST",
UpdateTargetId = "listingTable",
InsertionMode = InsertionMode.Replace
}))
{
<p>Filter listings by Workflow Status:</p>
#Html.DropDownListFor(m =>
Model.SelectedWorkflowStatus,
Enum.GetValues(typeof (WorkflowStatus))
.Cast<WorkflowStatus>()
.Select(v =>
new SelectListItem {
Text = v.ToString(),
Value = ((int) v).ToString()
}),
new { onchange = "$(this.form).submit()" })
}
As you can see, there are three objects that are being sent to the controller:
Model.SelectedCategoryGuid, Model.SelectedWorkFlowStatus and EntityName.
WorkFlowStatus is an enum, and for some reason, whenever I click on any of the enums in the DropDownList, it always comes out to be the FIRST one.
I have three Enum values which get inserted in to the DropDownList which are:
Draft, Published and Archived.
So, whenever I click on any one of them and when I hover over the variable in the Controller, I see that the parameter variable: workflowstatus is always Draft (which is the first one).
Does anyone know why the CORRECT enum isn't being passed over?
It's really bugging me...
The name of your DropDownList is SelectedWorkflowStatus. So make sure your controller action takes such parameter as argument:
[HttpPost]
public ActionResult FilterListingsWorkflow(WorkflowStatus selectedWorkflowStatus)
{
...
}
That's where you will get the correct value. I can see that you are setting some route values for your form:
new {
categoryguid = Model.SelectedCategoryGuid,
workflowstatus = Model.SelectedWorkflowStatus,
entityName = Model.EntityName,
}
But don't look the workflowStatus parameter in your action. This guy will contain the old value, the one that was hardcoded in the form when the view first rendered. The fresh value is stored in the selectedWorkflowStatus parameter coming from your DropDown.
All this being said the proper way to handle this situation is (as always in ASP.NET MVC) to use a view model:
public class MyViewModel
{
public Guid SelectedCategoryGuid { get; set; }
public WorkflowStatus WorkflowStatus { get; set; }
public string EntityName { get; set; }
public WorkflowStatus SelectedWorkflowStatus { get; set; }
}
that your controller action will take:
[HttpPost]
public ActionResult FilterListingsWorkflow(MyViewModel model)
{
// model.SelectedWorkflowStatus will contain the value from the DropDown
// model.WorkflowStatus will contain the initial value
...
}
Also please replace:
m => Model.SelectedWorkflowStatus
with:
m => m.SelectedWorkflowStatus
in your DropDown. You don't need to capture the model in a closure.

How do I add a Custom Query for a drop down and retain the View Model Pattern?

I've read many articles which they state that querying should not be placed in the Controller, but I can't seem to see where else I would place it.
My Current Code:
public class AddUserViewModel
{
public UserRoleType UserRoleType { get; set; }
public IEnumerable<SelectListItem> UserRoleTypes { get; set; }
}
public ActionResult AddUser()
{
AddUserViewModel model = new AddUserViewModel()
{
UserRoleTypes = db.UserRoleTypes.Select(userRoleType => new SelectListItem
{
Value = SqlFunctions.StringConvert((double)userRoleType.UserRoleTypeID).Trim(),
Text = userRoleType.UserRoleTypeName
})
};
return View(model);
}
The View:
<li>#Html.Label("User Role")#Html.DropDownListFor(x => Model.UserRoleType.UserRoleTypeID, Model.UserRoleTypes)</li>
How do I retain the View Model and Query and exclude the User Type that should not show up?
I think that you are doing it just fine.
Any way... all you can do to remove the querying logic from controller is having a ServiceLayer where you do the query and return the result.
The MVC pattern here is used correctly... what your are lacking is the other 2 layers (BusinessLayer and DataAccessLayer)... since ASP.NET MVC is the UI Layer.
UPDATE, due to comment:
Using var userroletypes = db.UserRoleTypes.Where(u=> u.UserRoleType != 1);
is OK, it will return a list of UserRoleType that satisfy the query.
Then, just create a new SelectList object using the userroletypes collection... and asign it to the corresponding viewmodel property. Then pass that ViewModel to the View.
BTW, I never used the db.XXXX.Select() method before, not really sure what it does... I always use Where clause.
SECOND UPDATE:
A DropDownList is loaded from a SelectList that is a collection of SelectItems.
So you need to convert the collection resulting of your query to a SelectList object.
var userroletypes = new SelectList(db.UserRoleTypes.Where(u=> u.UserRoleType != 1), "idRoleType", "Name");
then you create your ViewModel
var addUserVM = new AddUserViewModel();
addUserVM.UserRoleTypes = userroletypes;
and pass addUserVM to your view:
return View(addUserVM );
Note: I'm assuming your ViewModel has a property of type SelectList... but yours is public IEnumerable<SelectListItem> UserRoleTypes { get; set; } so you could change it or adapt my answer.
I don't see anything wrong with your code other than this db instance that I suppose is some concrete EF context that you have hardcoded in the controller making it impossible to unit test in isolation. Your controller action does exactly what a common GET controller action does:
query the DAL to fetch a domain model
map the domain model to a view model
pass the view model to the view
A further improvement would be to get rid of the UserRoleType domain model type from your view model making it a real view model:
public class AddUserViewModel
{
[DisplayName("User Role")]
public string UserRoleTypeId { get; set; }
public IEnumerable<SelectListItem> UserRoleTypes { get; set; }
}
and then:
public ActionResult AddUser()
{
var model = new AddUserViewModel()
{
UserRoleTypes = db.UserRoleTypes.Select(userRoleType => new SelectListItem
{
Value = SqlFunctions.StringConvert((double)userRoleType.UserRoleTypeID).Trim(),
Text = userRoleType.UserRoleTypeName
})
};
return View(model);
}
and in the view:
#model AddUserViewModel
<li>
#Html.LabelFor(x => x.UserRoleTypeId)
#Html.DropDownListFor(x => x.UserRoleTypeId, Model.UserRoleTypes)
</li>

Resources