ASP.net MVC - Passing an Id into a Partial View - c#

I have the following route in my MVC application:
/foobars/edit/{id}
The {id} in this case corresponds to the Id for my "Foobar" model.
In my Edit view I am doing the following:
#Html.Partial("~/Views/Notes/CreateNotePartial.cshtml", new CreateNoteViewModel())
The CreateNotePartial view uses a jQuery dialog and will POST to my NotesController using the following route:
/notes/create/{id}
The {id} in this case is NOT the same id as my Foobar id. My Foobar model has another property called UniqueId. I need to be able to pass this into my Partial view so that when I create the form to POST to the notes controller it passes in the right id. What is the best way to do this?
Right now I am doing the following:
// Foobar Edit View
#Html.Partial("~/Views/Notes/CreateNotePartial.cshtml", new CreateNoteViewModel(Model.UniqueId))
// Create Note Partial
#model CreateNoteModel
#using( Html.BeginForm("Create", "Notes", FormMethod.Post, new { id = Model.UniqueId }) ) {
}
Is there a better way to pass this to my partial view or is this the best way to do it?

Seems the best way to do it to me - I think your only other option is to pass it in ViewData, which everyone would tell you is not recommended for reasons of strong typing, magic strings, et al.
Certainly, it's the way that I do it (not that I'm the world's greatest authority of course).

From what it looks like, you're setting the form id to the model.UniqeId. That's just going to set the form's html element to whatever that model id is. I would not recommend doing that.
There's nothing wrong with using TempData (not the same as ViewData). TempData is made for passing a value from one view to another and then once it's accessed, it goes away. See this post for more.

Related

further clarification about passing data from controller to layout sub view in asp.net mvc 5

I guess I have a pretty standard problem as I want to pass certain data from an asp.net MVC 5 controller to a shared view, in my case navigation.
I have a template that shows username and userpicture in the navigation shared view, so I need to pass the respective data to it.
My layout structure:
Shared\Layout
Shared\Header
Shared\Navigation
%Body%
Shared\Footer
Where the Layout ist the master view and of course I also have my other views like Home\Index.
As you can imagine, I have to show the username and his userpicture in every view except the login/registration or any error views.
These views do not use the layout at all, so everytime a view is rendered using the layout structure, the user is already logged in.
So I was researching about ways to pass data from my controller to the navigation view, although my controller returns the Index view and would appreciate some clarification on their disadvantages and valid choices in my use case:
Use case:
My project has a pretty dumb MVC application that the user can access. Once he logs into the MVC app authenticates the user against the same webapi where it get's it's data from and stores the access token as well as other user details for further requests. I'm not yet sure where to store that data. As far as I understand it, the options would be Cookies, Session and local storage.
As I am pretty new to asp.net, MVC and C# in general, I didn't yet figure out how to make the [Authorize] Attribute work inside the MVC app so it can mark the user as authenticated :/
I guess the key problem is that the MVC app does not have access to the database and therefore cannot check the login and populate the User Identity.
How to transfer data from controller to view:
ViewBag: The easiest way of passing data to the view. It is not strongly typed and can be accessed in all views. I was told it is kind of a bad practise to use it and was advised to use viewModels.
ViewData: seems to be kind of the same thing as viewdata.
ViewModel: A strongly typed model that is passed to the view and needs to be declared in any view that uses it. So if I want to use it in my navigation view, I'd need to declare it there. The big disadvantage of this approach is that every viewmodel needs to have kind of a baseViewModel so they have a common structure which appearently can cause problems later down the road and also prevents me from inheriting other models to populate my viewModelStructure.
Cookies: Obviously I can store data in cookies during login and then access them in the view, but the cookies HAVE to be there so I would not be able to save this information in the session or local storage
Session: I can also store data in the session, but the session expires when the user closes the browser tab.
LocalStorage: This is pretty new to me so I can't judge it.
User Identity: I just discovered that I can also access the user's identity from Context.User.Identity.
Global Filter like the [Authorize] attribute or a custom one: If I understand it correctly, with a global filter I can populate needed data automatically in every controller action and exclude the ones that dont need it like Login/register etc. I'm not yet sure how to apply this way because of my project structure (see above).
RenderAction: I could also call another controller method via the RenderAction helper method to always render that section of the page.
How do you guys solve this problem?
If you need more clarification, please do ask.
Thanks :)
Use a base ViewModel. You can still use inheritance to build up functionality in your view models, they'll all just share a common base view model, as you said.
I'm not sure what problems you envisage with this approach, but I would suggest they're outweighed by the benefit of strongly typed, maintainable view models, that can be used by all your views, including partial views and _Layout.
A suggestion to get you started based on your layout structure:
public abstract class ViewModelBase {
public HeaderViewModel Header {get;}
public NavigationViewModel Navigation {get;}
public FooterViewModel Footer {get;}
public ViewModelBase(HeaderViewModel header, NavigationViewModel navigation, FooterViewModel footer) {
Header = header;
Navigation = navigation;
Footer = footer;
}
}
public class HeaderViewModel {
// properties
public HeaderViewModel(...) {
}
}
public class NavigationViewModel {
// properties
public NavigationViewModel(...) {
}
}
public class FooterViewModel {
// properties
public FooterViewModel(...) {
}
}

Get controller properties in HTML, is everything meant to go in a viewbag?

From what I read in various tutorials, or simply the sample project, the Controller use the ViewBag to store anything that will be dipsplayed on the page.
In the Controller I can just type ViewBag.AnythingIWant = "Foo";, and it'll render in the HTML. Apparently that's what is done in the sample project, at least for title and various texts.
But most of the text is hardcoded in the HTML and obviously I don't want that. Considering I'm not new to C# or MVC in Xamarin (mobile development), I feel like I should grasp this pretty quick, but I don't. Could someone clarify to me the following :
My Controller knows the ViewModel (which does most of the work) and himself uses the Model privately. I'm used (from iOS dev) for the controller to be the last layer of UI, and inside the controller I would just have all my labels and whatever I want, and I can fill them with whatever is available in the ViewModel.
Here, there is this HTML layer that I don't know how to connect to the controller.
I have a strong feeling that putting everything in the ViewBag cannot be the way to go. Could anyone briefly reveal the piece I am missing to use proper objects inside the HTML ?
Razor might be what's confusing me, considering whatever I add publicly in my Controller, I can't find it in the related HTML using #MyProperty
I know this is pretty broad question but I know that I only miss a small piece of knowledge to unlock everything.
As noted in the comments, pass a ViewModel to the View to be rendered!
Controller
public ActionResult Index() {
var viewModel = new MyViewModel { Name = "some string" };
return View("Index", viewModel);
}
Index.cshtml
#model MyViewModel #* Tell Razor which ViewModel to expect *#
#{ string name = Model.Name; }

MVC3 Razor Help required

I'm hoping you guys can answer me a question?
I've only just started out using ASP.NET MVC3 have come unstuck at a certain point. I've been learning this stuff from books and I'm slightly unsure on a few things.
Can a VIEW, only have one #Model reference?
At the moment I have a VIEW setup with a HTTP-POST on a ViewResult, that validates the data in the View, entered by the user and then "on post", passes this info to a method that writes it back to a database(ADO.NET - Access). Now I need to change my VIEW, so that I can replace a couple of my text boxes for Dropdownlistfor controls. The Data to populate these controls will need to be passed in from the Database.
Would I be correct in saying that this data needs to be passed in the HTTP-GET Viewresult of the page, and if so, can i reference more than one #Model in this same View (*.cshtml).
I have a class that takes in the user response, and this is referenced in the View. But will i need to create a new class for the dropdownlist data and reference that too. So that in the background I populate the data into a SelectListItem, pass it to the View and then populate each drop down control within the view?
I'm sorry if this is poorly written, very hard to explain, I find learning from books hard and I'm pretty stuck now. Any help would be appreciated. Just to give me an understanding of how this all wraps around. I'm comfortable with the C# syntax, but very unsure of MVC3!
There are two ways you can handle this.
Use a View Model.
In this scenario you have a class that contains your data model as well as other things required by the view, so something like this:
public class ViewModel
{
public MyDomainModel Model { get; set; }
public IEnumerable<SelectListItem> SelectListItems { get; set; }
}
Use ViewBag.
In this case you add everything extra into the ViewBag dictionary. So in the controller, you'd have stuff like this:
ViewBag.SelectListItems = new SelectListItem[] { ... };
Then you can reference in the view itself
#Html.DropDownList("myselectlist", ViewBag.SelectListItems)
I think that this will help you pluralsight mvc3 intro. It sure helped me

ASP.NET MVC 3 - DropDownListFor Fails when URL Parameter Also Exists with Same Name as View Model Parameter

I am not sure if this is a bug with the DropDownListFor extension or what, but we had the following:
http://mydomain.com/path/page?myparam=myvalue
In my View Model I have the following:
public string MyParam { get; set; }
public List<SelectListItem> ParamOptions { get; set; }
When I do the following in my View it fails to select the correct value:
#Html.DropDownListFor(x => x.MyParam, Model.ParamOptions, "Select Value")
However, when I change the parameter 'MyParam' in my view model to 'MyParam2' and update my View to use MyParam2 parameter instead, it will select the correct option item given the value of MyParam2. Before it would not when the parameter name was MyParam.
Has anyone else ran into this? Is this a bug with MVC 3 or is this a bad implementation on my part?
What about the URL mentioned,
http://mydomain.com/path/page?myparam=myvalue
The url has a queryString with key "myparam", since the name is same as property name and When the url is invoked it will add a ModelState value against "myparam".
ModelState["myparam"] will be "myvalue".
So when the page is loaded the dropdown will select "myvalue" from drop down.
This is a well known issue. It's not a bug, because this is by design. It's more of a design limitation.
There's nothing that can be done about it, just rename your parameter or rename the property.
This isn't much of an answer other than to say i've experienced the same behavior in a slightly different situation.
In my case I was calling a child action from the parent action and passing in a viewmodel specific to the child action, which shared some of the same property names with the parent's ViewData. When my child action partial view was rendered, it was showing viewdata from the parent controller as opposed to what was in the viewmodel I was passing to the child action. In this situation looked like view data from the parent action was polluting my child action viewmodel when the properties both had identical names.
So it looks like the binding sometimes gets confused as to what value to bind when there are name collisions. In my case I just renamed the properties in the child viewmodel to prevent this collision, but it had me pulling my hair out figuring out why the wrong value was there.
If somebody has a real answer as to why this happens I would like to know as well. To me it comes across as a binding bug, but perhaps there is an intention here.

TextBoxFor<DIFFERENT VIEW MODEL>() for AJAX operation?

I have a view model ViewModel1 that has all of the proerties for my view.
In my view I need 2 text boxes that will be used in a AJAX call to another action that has different parameters then the view I'm currently on.
Here's what I'd like the code to look like:
#using(Ajax.BeginForm("AjaxAction", "Home", new { TestId = Model.TestId }, new BOHAjaxOptions(), new { id = "newform", name = "newform" }))
{
#Html.TextBoxFor<DIFFERENT VIEW MODEL>(model => model.FIELD1)
#Html.TextBoxFor<DIFFERENT VIEW MODEL>(model => model.FIELD2)
Submit
}
I figured this would make sense since I want to be able to use the "AjaxAction" action on different views from different controllers since this action is going to be called from multiple parts on the site.
Or am I just not seeing the right picture here? Should I just include FIELD1 and FIELD2 in all of the ViewModels that need to call this AJAX action?
You should include all the data needed for the view in the view model, including data that might be posted back to another action as a separate model. Note that generally there isn't a one-to-one correspondence between a entity model and a view model. In nearly all cases my view models include either more or less data that the primary entity that the view is focused on.

Categories

Resources