I'll try to explain what I'm trying to do. I have 2 tables in my application. One is Project and the other is Bug. One proyect can have several bugs.
I'm able to add/edit/delete projects. To each project in the database I added an ActionLink so if you click over its name, it should show all the bugs related to that project.
I tell "should show" because I'm able to see the new page with the ID on the URL which is fine, but I haven't been able to assign a specific Project ID to the BUG.
For example:
BUG has description, status, date...and Project ID (which i would like to use to filter my bugs)
So what I would like to do is to get the ID of the project which has been clicked, so when I hit create action, i can store the ProjectID in the BugDatabase with all other values that are stored automatically by MVC.
Are you passing the value with the action link?
#Html.ActionLink(
"BUG",
"PROJECT",
"Project",
new {
ProjectId = myProjectId,
}
)
Related
I apologize if this is a newb question. I'm more experienced with Windows forms and just getting started with MVC. I have a class called PackagedProduct which consists of a Package and a Product that are selected via drop down list and represented by their own models.
PackagedProduct
Sometimes though, the Product may not exist yet so I have an ActionLink that directs to the Create action of Product.
#Html.ActionLink("Create New Product", "Create", "Products");
Product
How can I allow the user to create the new Product, but when the create button is pressed to return to the PackagedProduct view where it originated with the existing data still populated(in this case UPCCode and Package)? The PackagedProduct won't have been created yet because it is missing required data until the correct Product is created so I can't just pass back the PackagedProductID. Thoughts?
As per a question that I asked yesterday I was trying to find a way to dynamically create more text boxes and have those map to my view's model so upon post to the server it will grab all the dynamically(js) generated text boxes and post that to an object such as a List.
To give an example of this confusing question:
I have a textbox that is labeled "Primary Contact" and the ticket creator can enter the contacts name and phone number into this box. What I want to do essentially is, switch this to three text boxes. One for Name, Email and PhoneNumber instead of one box. Then I will create some javascript that will dynamically create three more boxes to add another contact to this List collection. Then when the user submits the form to modify or create the ticket it passes this collection inside the model to the controller. However with petapoco it is a little confusing. Let me show you the controller:
[HttpPost]
public ActionResult ModifyTicket(Ticket model)
{
string userString = User.Identity.Name.Replace("ONHOLD\\", "");
if (ModelState.IsValid)
{
model.CreatedDate = DateTime.Now;
model.LastUpdateBy = Util.GetEmployeeIdByName(userString);
model.LastUpdate = DateTime.Now;
model.IsComplete = false;
model.ClientString = Util.GetClientNameById(model.ClientId);
model.LocationString = Util.GetLocationNameById(model.LocationId);
model.Update();
SuccessMessage = "You have successfully updated ticket number: " + model.TicketId + " for the following client: " + model.ClientString + ".";
return RedirectToAction("Index");
}
ErrorMessage = "Woops! Something went wrong, please check back in a few moments, if the problem persists please contact development.";
return RedirectToAction("Index");
}
The simple answer to this would be that my database model would contain a List object for this exact reason. However, I am using PetaPoco and I'm not entirely sure how it would be done. I could manually add in a collection to my Database model but when I regenerate my model based on any database schema changes I will lose any changes I've made to the file.
I am also using a partial class that my view uses for validation using DataAnnotations. However this class is identical to the database model it just contains DataAnnotations to provide client-side validation.
If anyone understands what I'm trying to accomplish I would be more than happyto provide more information to clarify any missing pieces. I just need a resolution to this as I can't find a solid way to go about resolving this issue!
Not entirely sure what you mean but it's easy to model bind from/to a list with MVC as you may already know. As for saving a deep object like this I'd use the [Ignore] attribute on the Ticket.List so it isn't persisted and handle it separately. I'd load the Contacts in separately from the Ticket object then manually add them to the Ticket object, alternatively use a join query and try the one-to-many approach to load it all in one go.
I think you're expecting Petapoco to update all in one? This won't happen you'll need to break it up. Hard to say from what you've written so far. There won't be a long list of contacts (from the sounds of it) so just insert or update them one by one.
Well that might help, or might not.
I have a details page containing a form field named UserId. On the same page i have another search form with a field also named UserId.
I am using Html.LabelFor(vm > vm.UserId) and Html.TextBoxFor(sm > sm.UserId) on the two different view models, vm being the view model and sm being the search model. (Yes, the UserId property on the two models has identical names - because they are the same domain property.
When i navigate to the page, the populated UserId on the vm is inserted into BOTH form fields named UserId by MVC. Even the sm.UserId are empty.
That is my initial problem. There are a few ways ti avoid that. My solution was to use the Prefix flag for the sm.
[HttpGet]
public ActionResult Search([Bind(Prefix = "Search")] SearchFormViewModel searchFormViewModel, PagingViewModel pagingViewModel)
{
This will provoke MVC to render a Search.UserId on the fieldname in the search form, but the property in code will still be named UserId.
This solution seems to work great!
BUT:
Now i have to address the search.UserId on a route from Global.asax.
I map the route like this:
routes.MapRoute(
"MyRouteName",
"ControllerName/User/{Search.UserId}",
new { controller = "ControllerName", action = "Search" }
);
My problem is that MVC can't map the Search.UserId (because of the .) to fit the UserId (prefixed with Search) in the action shown above.
So it seems like MVC has a prefix-feature, that are actually nok fully supported through the Route-handler.
Ofcourse i could rename the Search.UserId to Search_UserId, but then the name dosent match the name MVC expects in the recieving action above. (expects Search.UserId) Renaming The UserId property of the search model would fix the issue, but since it is the same value in the domain, this seems like a workaround.
Am I missing something here about the usage of the Prefix feature or is this just not possible?
So... I've been thinking about this for a while now. - And a colleague of mine suddently showed me the light.
The problem lies where MVC maps the object to a route dictionary.
See the user
wount work. Because MVC can not handle the .(dot) in the object name.
but since the object name is just a string key in the routevaluedictionary, mapping it my self did the trick:
See the user
I have three classes - Employee, Project and TrainingProgram. Then I have a fourth class, TrainingRecord which consists of an Employee, the Project they trained for, the TrainingProgram they completed and the date they completed it on.
Users can create new TrainingRecords from two spots - either through an Employee (they select the Project and TrainingProgram, then submit) or through a Project (they select an Employee and a Training Program, then submit).
When inside the Create page for TrainingRecord, what's the best way to tell which parent I came from (the details page of an Employee or the details page of a Project) and how would I redirect the page back to that parent after the new TrainingProgram is submitted?
You could pass a returnUrl parameter to the controller action which indicates where to redirect to in case of success.
I would've used session variables but you could use querystring as well.
My domain model is this: we have a bunch of schools as the root of the "hierarchy". Each school has teachers and courses, and each course has one teacher. I am trying to model this with the logic of the mvc framework and I 'm quite confused. For example, the \school\details\x should give the first page of a school. That should contain a link to a list of its teachers, and a list to each courses.
A list of teachers means that the index action should be parametric to the school the user is looking at: \teacher\id where id is the school. The same with the course list. And then create teacher or course should also be parametric to what school we are looking at:\teacher\create\x where x=school.
How do I carry around the school id? Is there some neat way to do it, or do I need to pass it around all the time, into every view that needs it? It also makes the site URLs very cryptic. I was thinking of a way to make the url structure like {school-alias}\{controller}\{action}\{id}, still I have to find a way to pass around the school. If this is accomplished, then I need to implement some kind of filter that will not allow a user to perform certain actions if the schoolId he is requesting does not match the one in his profile.
I figure that if I 'm carrying the schoolid around the URL, the site is more REST-like, compared to, for example, getting the schoolId from the user's profile.
I would create acronym for every school. For example:
School no. 1 - ABC
School no. 2 - DEF
If i wanted to list teachers, I would write
http://site-address/ABC/teachers/list or just http://site-address/ABC/teachers
To show basic information about school
http://site-address/ABC
The code for routing would be:
routes.MapRoute(
"Default", // Route name
"{acronym}/{controller}/{action}/{id}", // URL with parameters
new {controller = "School", action = "Details", id = ""} // Parameter defaults
);
I would create authorization action filter on teachers,school and classes controller to check if user has access to school defined by acronym parameter in URL. You can check it by comparing filterContext.RouteData.Values["acronym"] with data stored in profile.
Write an extension method to overload rendering of links that extracts the school identifier ( acronym or whatever you choose to use ) from the routing data and adds it to the route values already passed in. This way your action can choose to use the identifier if it is present but is not required to add it to the view data and you do not have to remember to include it in any action links ( you just have to remember to use your action link overload ).
I would make the action link overload quite obviously different so anyone following behind you can see you are doing something unusual. This could be as simple as Html.SchoolActionLink( ...).
For example:
If your url is http://mydomain.com/abc/teachers/list and your route is defined as {school}/{controller}/{action} then the route value dictionary will have the value "abc" at the key "school". The route values can be accessed via HtmlHelper.ViewContext.RouteData.Values.
In the end I 'm answering my own question.
The real solution to this is :Restfull Routing. It implements the functionality in RoR, which is exactly what I need. Too bad this is not a requirement from more people so that it can go into mvc-trunk.