I am looking for a partially edit my model - the scenario is i want to display 5 fields and ,2 fields should be editable, and when post happens it should update the editable fields, Strongly type view provide either fully editable view or detail view , how can i have both in conjunction . Any advice or help will be appreciated.
<tr><td>Booking ID</td><td><%: Model.ID %></td></tr>
<tr><td>Transaction No.</td><td><%: Model.TransactionNumber %> (<%: Model.PaymentProvider %>)</td></tr>
<tr><td>Date</td><td><%: String.Format("{0:g}", Model.DateAdded) %></td></tr>
<tr><td>Name</td><td><%: ViewBag.account.FirstName %> <%: ViewBag.account.LastName %></td></tr>
<tr>
<td>
<div class="editor-label">
<%: Html.Label("Event") %>
</div>
</td>
<td>
<div class="editor-field">
<%: Model.Event.Name %><%: Model.Event.Description %>
</div>
</td>
</tr>
<tr><td valign="top">Address</td><td><%= HtmlFormatting.FormatAddress(ViewBag.address)%></td></tr>
<tr><td>Cost</td><td>£<%: String.Format("{0:F}", Model.Cost) %></td></tr>
<tr><td>Status</td><td><%: ViewBag.status %></td></tr>
Thnx
Your implementation is all wrong here. First of all, don't use <table>'s everywhere for layout, you can use the MVC template, just float the div tags left.
You need a ViewModel within which you can reference your Booking object which I assume is a database object?
Something like...
public class BookingViewModel
{
public Booking Booking { get; set; }
}
And when you call your View from your controller pass it in
public ActionResult Index()
{
return View(new BookingViewModel());
}
Then you can add a Post action result to your controller within which you can update your properties
[HttpPost]
public ActionResult Index(BookingViewModel model)
{
//Update your properties
return View(model);
}
Related
Following is my Architecture of an application. I am confuse with whether I understood MVC correct or not? My Architecture is right or not?
View - interacts with the user, it has HTML part, on submit the form it calls controller
Controller - it checks for information added is valid or not? (not database point of view. it will just check for weather all the mandatory fields are filled or not?) decides which model to call.
Model - it contains class of view. and also some methods like add,modify or delete to deal with the database.
Is this correct or making some mistake?
Following is sample of my code
Controller:
public ActionResult AddCustomer(CustomerModel model)
{
if (ModelState.IsValid)
{
model.AddCustomer();
return RedirectToAction("Index", "Home");
}
return (View("AddCustomer",model));
}
Model:
public class AddBookModel
{
[Required(ErrorMessage = "The ISBN is required.")]
[DisplayName("ISBN")]
public String ISBN { get; set; }
[DisplayName("Title")]
[Required(ErrorMessage = "The Title is required.")]
public String Title { get; set; }
[Required(ErrorMessage = "The Publisher is required.")]
[DisplayName("Publisher")]
public String Publisher { get; set; }
public void AddBook()
{
using (BBBDataContext DCBook = new BBBDataContext())
{
Book tableBook = new Book()
{
ISBN = this.ISBN,
Title = this.Title,
Publisher = this.Publisher,
}
DCBook.Books.InsertOnSubmit(tableBook);
DCBook.SubmitChanges();
}
}
View:
<% using (Html.BeginForm()) {%>
<%= Html.ValidationSummary(true) %>
<fieldset>
<legend>Insert Book Record</legend>
<table id="displayform" cellspacing="0" cellpadding="5">
<colgroup>
<col span="1" style="text-align:right" />
<col span="2" style="text-align:left" />
</colgroup>
<tr>
<td class="editor-label">
<%= Html.LabelFor(model => model.ISBN) %>
</td>
<td class="editor-field">
<%= Html.TextBoxFor(model => model.ISBN) %>
<%= Html.ValidationMessageFor(model => model.ISBN) %>
</td>
</tr>
<tr>
<td class="editor-label">
<%= Html.LabelFor(model => model.Title) %>
</td>
<td class="editor-field">
<%= Html.TextBoxFor(model => model.Title) %>
<%= Html.ValidationMessageFor(model => model.Title) %>
</td>
</tr>
Your understanding of MVC is good.
The view only contains visual elements that will be displayed and doesn't contain any logic code.
The controller is listening to the view's events (mouseClick, lostfocus...), interact with the model, do verifications...
And the model contains your business class and interacts with databases and others external services.
I have the following model:
#model SmartSEOModel
public class SmartSEOModel
{
public SmartSEOSettingsModel SmartSEOSettingsModel { get; set; }
public SEOTemplateModel SEOTemplateModel { get; set; }
}
In my view I have a partial view which I call like this:
#using (Html.BeginForm())
{
some razor code here
<div id="pnlSmartSEO">
#Html.Partial(ViewNames.SmartSEOController_SEOTemplate, Model.SEOTemplateModel)
</div>
}
In the partial view there are some form fields bound to the SEOTemplateModel.
The problem is that when I receive the SmartSEOModel in my HttpPost action, the SEOTemplateModel is null. As if the SEOTemplateModel has been passed by copying it to the partial view.
Please advise why this is and how to workaround it.
Many thanks
My partial view looks like this:
#Html.Telerik().TabStrip().Name("SmartSEO").Items(x =>
{
x.Add().Text(T("Admin.SmartSEO").Text).Content(GetSmartSEOUI().ToHtmlString()).Selected(true);
})
#helper GetSmartSEOUI()
{
#(Html.LocalizedEditor<SEOTemplateModel, SEOTemplateLocalizedModel>("SmartSEO-Localized",
#<table class="adminContent">
<tr>
<td class="adminTitle">
#Html.NopLabelFor(model => model.Locales[item].CategoryTitleSEOTemplate):
</td>
<td class="adminData">
#Html.EditorFor(model => model.Locales[item].CategoryTitleSEOTemplate)
</td>
</tr>
</table>,
#<table class="adminContent">
<tr>
<td class="adminTitle">
#Html.NopLabelFor(model => model.CategoryTitleSEOTemplate):
</td>
<td class="adminData">
#Html.EditorFor(model => model.CategoryTitleSEOTemplate)
</td>
</tr>
</table>
))
}
My HttpPost action looks like this:
[HttpPost]
public ActionResult Configure(SmartSEOModel smartSEOModel)
{
var seoTemplate = SEOTemplateService.GetSEOTemplateById(smartSEOModel.SEOTemplateModel.Id);
if(seoTemplate == null)
{
throw new ArgumentException(String.Format("No SEOTemplate found with Id {0}", smartSEOModel.SEOTemplateModel.Id));
}
if (!ModelState.IsValid)
{
RedirectToAction("Configure");
}
SettingService.SaveSetting(smartSEOModel.SmartSEOSettingsModel.ToEntity());
seoTemplate = smartSEOModel.SEOTemplateModel.ToEntity(seoTemplate);
SEOTemplateService.UpdateSEOTemplate(seoTemplate);
UpdateLocales(seoTemplate, smartSEOModel.SEOTemplateModel);
//activity log
CustomerActivityService.InsertActivity("EditSEOTemplate", LocalizationService.GetResource("ActivityLog.EditSEOTemplate"));
SuccessNotification(LocalizationService.GetResource("SevenSpikes.NopSmartSEO.Admin.SEOTemplate.Notifications.SEOTemplateEdited"));
return View("SevenSpikes.Nop.Plugins.SmartSEO.Views.Configure", smartSEOModel);
}
Becuase you don't have a form within your partial view, it will not persist the data. Try using #Html.EditorFor instead of #Html.Partial.
So your main view would look like
#using (Html.BeginForm())
{
some razor code here
<div id="pnlSmartSEO">
#Html.EditorFor(model => model.SEOTemplateModel)
</div>
}
You would then need to move your partial view into a template. Rename your partial view to EditorTemplates\SEOTemplateModel.cshtml and place it in the same location where your main view is.
You will also need to make your template strongly typed: #model [namespace].SEOTemplateModel
The issue I am having is when i pass a populated object to a view that doesn't display all of the properties.
public ActionResult Edit(Guid clientID)
{
Property property = PropertyModel.GetPropertyDetails(clientID);
return View("Edit", "Site", property);
}
View:
<%# Page Title="" Language="C#" Inherits="System.Web.Mvc.ViewPage<WebFrontend.ViewModels.Property>" %>
<% using (Html.BeginForm())
{%>
<%: Html.ValidationSummary(true, "Property update was unsuccessful. Please correct the errors and try again.") %>
<fieldset>
<legend>Edit Account: <%: Model.ClientAccountNo %></legend>
<div class="editor-label">
<%: Html.LabelFor(model => model.ClientName)%>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.ClientName)%>
<%: Html.ValidationMessageFor(model => model.ClientName)%>
</div>
<p>
<input type="submit" value="Update Property" />
</p>
</fieldset>
<% } %>
When submitted the Property object is passed to this controller method but all of the properties not used in the view are null or empty including Model.ClientAccountNo which is present on the view before submitting.
[HttpPost]
public ActionResult Edit(Property property)
{
if (ModelState.IsValid)
{
bool success = PropertyModel.UpdateProperty(property);
if (success)
{
// property has been updated, take them to the property details screen.
return RedirectToAction("Details", "Property", new { clientID = property.ClientID });
}
else
{
ModelState.AddModelError("", "Could not update property.");
return View("Activate", "Site", property);
}
}
// If we got this far, something failed, redisplay form
return View("Edit", "Site", property);
}
I can't find anything similar on the web, any explanation for why this is happening and how to fix it would be appreciated.
This is the way MVC works - it tries to construct an object of the action parameter type from the values in the route, form and query string. In your case it can only get the values in the form collection. It does not know anything about the values that you have stored in your database.
If you are only interested in certain properties you would be better off doing a specific view model with just these on - then you can validate for this specific case.
If you store values in hidden fields keep in mind that these can be manipulated - if this is a problem definitely go with a specific view model with only the editable fields on.
Since you are not passing unused properties in URL, then you will have to render hidden fields for them. Use Html.HiddenFor method.
Does anyone know how to get POST values for MODELVIEW Pattern below. I can display the MenuItem as Checkboxes and Radio buttons,
but when user submits the form i.e. POST, ModelViewTest is null. I'm expecting List of MenuItems that user have selected.
public class ModelViewTest
{
public IEnumerable<MenuItem> MenuItemList { get; set; } //Will be displayed as listboxes and checkboxes
public Restaurant restaurant {get;set;}
}
ACTIONS:
public ActionResult Edit()
{
//some code here
}
return View(new ModelViewTest());
}
[HttpPost]
public ActionResult Edit(ModelViewTest model)
{
//I'm not getting List of MenuItems
return View();
}
MenuItem Class:
public class MenuItem
{
public string MenuItemCode{get;set;}
public string MenuItemDescription{get;set;}
public string UIType {get;set;} //This determines whether it's radio or checkbox
public string UIGroupType {get;set;} //Determines the Group for radio/checkbox.
}
public class Restaurant
{
public string restaurantName{get;set;}
public MenuItem MenuItem{get;set;}
}
Update
Please see my View code snippet below:
<table>
#foreach (var menu in Model.MenuList)
{
if (menu.UIType == "Radio")
{
<tr>
<td align="left">
<input id="MenuCheckboxRadio" name="#Menus.UIGroup" value="#Menu.MenuItemCode" type="radio" />
<label>#Menu.MenuItemDescription</label>
</td>
</tr>
}
else
{
<tr>
<td align="left">
<input id="MenuCheckbox" name="#Menus.UIGroup" value="#Menus.#MenuItem" type="checkbox" />
<label>#Menu.MenuItemDescription</label>
</td>
</tr>
}
i++;
}
</table>
In order to get the list of menu items in the POST action you need their corresponding values must be included in the html <form> and because this is a collection follow the standard naming convention so that the default model binder can parse them.
First you should show us your view to know how you render your ViewModel.
However try this:
make partial view to be editor template for your MenyItem
<%# Control Inherits="ViewUserControl<MenyItem>" %>
<%: Html.TextBoxFor(m => m.MenuItemCode) %>
<%: Html.TextBoxFor(m => m.MenuItemDescription) %>
.......
then in your view make for loop NOT foreach:
<%# Page Inherits="ViewPage<ModelViewTest>" %>
<% using (Html.BeginForm()) {%>
<% for (int i = 0; i < 3; i++) { %>
<%: Html.EditorFor(m => m.MenuItemList[i]) %>
<% } %>
<% } %>
And please see this answer
Please see my View code snippet below:
<table>
#foreach (var menu in Model.MenuList)
{
if (menu.UIType == "Radio")
{
<tr>
<td align="left">
<input id="MenuCheckboxRadio" name="#Menus.UIGroup" value="#Menu.MenuItemCode" type="radio" />
<label>#Menu.MenuItemDescription</label>
</td>
</tr>
}
else
{
<tr>
<td align="left">
<input id="MenuCheckbox" name="#Menus.UIGroup" value="#Menus.#MenuItem" type="checkbox" />
<label>#Menu.MenuItemDescription</label>
</td>
</tr>
}
i++;
}
</table>
Using the Authors/Books catalog example, let's say I want to edit the info for the books of a specific author.
When someone navigates to domain.com/Books/Edit/2, I want to display an edit view for all the books where Author_ID = 2. Among the various book info is the book category (fiction, non-fiction, textbook, whatever) These categories are in their own table and are referenced by a Category_ID.
What's the best way to set up the edit form?
Currently in my controller I have something like this:
public ActionResult Edit(int id)
{
IQueryable<Book> books = bookRepository.FindBooksForAuthor(id);
return View(books);
}
And in my partial view:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IQueryable<Authors.Models.Book>>" %>
<%= Html.ValidationSummary("Edit was unsuccessful. Please correct the errors and try again.") %>
<% using (Html.BeginForm()) {%>
<fieldset>
<legend>Fields</legend>
<%var i = 0;
foreach (var book in Model)
{%>
<p>
<label for="Category_ID">Category_ID:</label>
<%= Html.TextBox("Category_ID", book.Category_ID)%>
<%= Html.ValidationMessage("Category_ID", "*")%>
</p>
<p>
<label for="Description">Description:</label>
<%= Html.TextBox("Description", book.Description)%>
<%= Html.ValidationMessage("Description", "*")%>
</p>
<%i++;
} %>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
<% } %>
Is my Inherits set properly at the top of the view since I'm passing an IQueryable object?
More importantly, how do I get the Category_ID field to be a DropDown with the correct category selected?
Can I just send the data for the dropdown to the view and figure out the selected item at the view level?
ViewData["categories"] = new SelectList(_db.BookCategories.ToList().OrderBy(b => b.Category_Title), "Category_ID", "Category_Title");
You could create view model class containing list of books and select list of categories:
public class BooksEditViewModel
{
public IQueryable<Authors.Models.Book> Books { get; set; }
public IQueryable<BookCategory> BookCategories { get; set; }
}
Then use BooksEditViewModel as view model
System.Web.Mvc.ViewUserControl<BooksEditViewModel>
and code dropdown with
Html.DropDownList("Category_ID", new SelectList(Model.BookCategories,"Category_ID", "Category_Title",book.Category_ID);
You should also read about list binding:
http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx