Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
How i can achieve passing data from controller to view without any action on view.
In my project ,
Event handler will raise an event in controller that will change the data of view in MVC.
I was searching for the answer and i come to know that
There should be some action on view but i dont need it.
EventHandler will raise an event and that will pass data to view
You obviously want to fire server events on the client, don`t you?
To achieve this you need to use SignalR. You can find a very good article here:
http://www.asp.net/signalr/overview/signalr-20/getting-started-with-signalr-20/tutorial-getting-started-with-signalr-20-and-mvc-5
In your controller:
public ActionResult getID()
{
string qry = "SELECT COUNT(JobID) FROM tblDriverJob";
IEnumerable<int> data = db.Database.SqlQuery<int>(qry);
int newFuelID = data.Single() + 1;
string i = Convert.ToString(newFuelID);
return new ContentResult { Content = i };
}
and then in your View
<div class="form-group ">
#Html.LabelFor(model => model.JobID, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.JobID, new { htmlAttributes = new { #class = "form-control", #Value = #Html.Action("getID"), #readonly = "readonly" } })
#Html.ValidationMessageFor(model => model.JobID, "", new { #class = "text-danger" })
</div>
</div>
This will fill this with the results from my Query.
NOTE: This will return a single value (count+1 to get new jobID) from my query. This design can also be used (with a little 'jigging' for a Drop down list (where I would return a list to the view).
normally there are two ways for passing values from controller to view
1) you can store your values in ViewBag or in ViewData, this is preferable when your value is simple like a string, message,any id etc,
2) But if your data is of complex type like a search query result, then you should create a model with properties to store your multiple values, and then pass this model to the view while returning to view from controller's action (i.g. return (viewname, modelObject)), then you can access this model by defining the model at the top of your view like this #model yourmodelclassname, and then you can access each property of this model on your view by using the "Model" keyword.
Related
I don't know how to sum up what I'm trying to do in the title properly! Basically I have created a controller with EF6 and one foreign key of the Client table is MJTopicsID which links to the MJTopics table, a table of 26 topics. In the add and edit view I want the MJTopicsID to be a drop down menu displaying all the topics available however when you select it and click to add or edit an entry it adds it to the Client table as the MJTopicsID foreign key number? How do I go about this so I can apply it to all of my views.
This is the dropdown menu I created in the edit view however it just shows numbers 1-26 and if I change it to the topics variable it doesn't know it as obviously its not in the open model, thanks!
<div class="form-group">
#Html.LabelFor(model => model.MJTopicsID, "MJTopicsID", htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.DropDownList("MJTopicsID", null, htmlAttributes: new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.MJTopicsID, "", new { #class = "text-danger" })
</div>
</div>
If I understood correctly then you want to display some readable value and save some db specific value like foreign key Id in this case.
In the view for helper method "DropDownList" you can give second parameter of type IEnumerable type as a list of your options like this:
View:
#Html.DropDownList("MJTopicsID",
(List<SelectListItem>)#ViewBag.MJTopics,
htmlAttributes: new { #class = "form-control" })
Action:
public ActionResult Index()
{
ViewBag.MJTopics = new List<SelectListItem>() {
new SelectListItem(){Text = "Topic1", Value ="1" },
new SelectListItem(){Text = "Topic2", Value ="2" }
};
return View();
}
SelectListItem has two properties which you can map with your models.
Also you can use your model with "Text" as value to display and "value" as value to use.
Let "topics" is your list model for topics
then you can write it as
topics.Select(
x=> new SelectListItem()
{
Text = x.Id,
value =x.Desc
})
This is the one way of doing it.
I hope it will solve your problem.
I wanted to add an answer if anyone is new to EF6 and is trying to do the same thing.
In the controller for the actionresult you are trying to do this for, so in my case create it will create a viewbag variable this was mine:
ViewBag.MJTopicsID = new SelectList(db.MJTopicss, "ID", "ID");
I changed it to:
ViewBag.MJTopicsID = new SelectList(db.MJTopicss, "ID", "topicalTF");
The topicalTF is the variable for the topics available and this showed all the topics but would save it as the ID, hope this helps!
I have created the custom "DataType" annotation to use on the model object to tell this is the date field on the view. ([DataType("Date")]) If I use #Html.EditorFor(model => model.DateCreated), it will act as a date field and pup up the JavaScript date picker. This is the template I am using under EditorTemplates
#inherits System.Web.Mvc.WebViewPage<DateTime>
<div class="input-append date" data-date="12-02-2012">
<input type="text" class="span2">
</div>
View -
<div class="control-group">
#Html.LabelFor(model => model.DateCreated, new { #class = "control-label" })
<div class="controls" id="date-container">
#Html.EditorFor(model => model.DateCreated, new { #class="input-append date"})
#Html.ValidationMessageFor(model => model.DateCreated, null, new { #class = "help-inline" })
</div>
</div>
Model -
[Display(Name = "Date Created")]
[DataType("Date")]
public DateTime DateCreated { get; set; }
Controller -
public ActionResult Create(int id)
{
// Attempt to get new customer object
GetPaymentResponse paymentResponse = _BillingService.GetPayment(id);
// Check whether response was successful
if (paymentResponse.State == BaseResponseState.Valid)
{
paymentResponse.Payment.Type.AvailableOptions = paymentResponse.Payment.Type.AvailableOptions.Where(x => x.Value != "BalancingTransaction").ToList();
ViewData.Model = paymentResponse.Payment;
return View();
}
}
I need to pass some additional value to my view via datatype from the model.
E.g. [DataType("Date"), Format("dd/mm/yy"), StartDate("12-02-2012")]
Could you please let me know how can I grab these additional value from the template? (I am new to ASP.Net MVC and I am using MVC 3)
Thanks
If you specify extra information using attributes, the information must be constant for all the instances of the class in which you define the member. I.e. the StartDate will be the same for all instances of your model, becasue the start date specified in the attribute must be a constant.
If that serves your purpoes, you can use a custom metadata provider to get specific metadata in your model from your custom attributes.
If you need to pass different data fro each case, you have to use any of the overloads of EditorFor which allows to pass extra view data. Then you can read that extra information from the ViewData in your template.
Be warned that there are some caveats in the metadata providers and custom template implementations, and registration. Take into account if your type can be made nullable, like DateTime?
If you use the Model Binding it should take the value properly I believe.
In your view, set the model on the first line, line this:
#model MyViewModel
and then in your controller, instead of passing the Model through the ViewData, do something like this:
var model = new MyViewModel();
// do stuff with your model here
return View(model);
Assuming that StartDate is a property of Payment
<div class="control-group">
#Html.LabelFor(model => model.StartDate, new { #class = "control-label" })
<div class="controls" id="date-container">
#Html.EditorFor(model => model.StartDate, new { #class="input-append date"})
#Html.ValidationMessageFor(model => model.StartDate, null, new { #class = "help-inline" })
</div>
</div>
I have a case where I have a page displaying an order and tabs that display the order details. The order details are quite complex and since they are the same layout, I want to use a partial view or editor template that will generate the form.
The problem is the result is multiple duplicate form input id's are generated (one for each order detail. For example, I have:
foreach (var orderDetail in Model.OrderDetils)
{
#Html.EditorFor(model => orderDetail, "WorkOrder", orderDetail)
}
I've read much about this and see solutions where it is recommended to use an editortemplate, but that solution only works when you have the same form to render, but passing it different model properties so the control id's prefixes will differ...ie. like this solution.
In my case, this won't work as the model property I am passing is always the same.
So how else can I create unique Id's in the partial or editor template that will also bind.
I know instead of:
#Html.EditorFor(model => model.WOHdr.Attribute1)
I could do:
#Html.TextBoxFor(model => model.WOHdr.Attribute1, new { id = Model.Id + "_Attribute1" })
But then it won't bind when it passes to the controller.
Thoughts?
Try this
#Html.TextBoxFor(model => model.WOHdr.Attribute1, new { #id = #Model.Id + "_Attribute1" })
Use "#"+dynamic value. Now You will get unique Id's
In EditorFor you can use like this
#Html.EditorFor(model => model.WOHdr.Attribute1, null, "id=" + #Model.Id + "" )
the id will generate like this
id="id_1", id="id_2" and so on..
<input id="Checkbox1_#(test.TestId)" type="checkbox" />
i hope upper code will help you
I get validation message always when I open this page (even first time), even if I choose value in one of dropdown lists, message doesn't go away. If I choose values in both I can submit form but messages still doesn't go away.
Snippet is Linq to sql class and LanguageID and SnippetTypeID are ints, I assume this happens because I pass empty model to View so LanguageID and SnippetTypeID are null and AFAIK Linq to Sql classes have required on non-nullable ints.
How can I fix this so validation messages doesn't appear before user tries to submit form, and if one of dropdown lists get selected to remove validation message.
View
#model Data.Snippet
#using (Html.BeginForm("Save", "Submit", FormMethod.Post))
{
<h1 class="subtitle">Submit new snippet</h1>
<h4>Title</h4>
#Html.TextBoxFor(snippet => snippet.Title, new { #class = "form-field" })
<h4>Language</h4>
#Html.DropDownListFor(snippet => snippet.LanguageID, new SelectList(#ViewBag.Input.Languages, "ID", "Name", #Model.LanguageID), "Choose Language", new { #class = "form-select" })
<p>#Html.ValidationMessageFor(snippet => snippet.LanguageID , "You must choose language", new { #class= "validation-message"})</p>
<h4>Snipet type</h4>
#Html.DropDownListFor(snippet => snippet.SnippetTypeID, new SelectList(#ViewBag.Input.SnippetTypes, "ID", "Name", #Model.SnippetType), "Choose snippet type", new { #class = "form-select" })
<p>#Html.ValidationMessageFor(snippet => snippet.SnippetTypeID,"You must choose snippet type", new { #class= "validation-message"})</p>
<h4>Text</h4>
#Html.TextAreaFor(snippet => snippet.Text, new { cols = "20", rows = "10", #class = "form-field" })
<input type="submit" value="Submit Snippet" />
}
Controller
//Controllers are not finished Save() should have
//code to actually insert to db after I fix validation
// GET: /Submit/
//
public ActionResult Index()
{
Snippet model = new Snippet();
SubmitModel input = new SubmitModel();
ViewBag.Input = input;
return View(model);
}
public ActionResult Save(Snippet snippet)
{
return View();
}
Model
Model is Linq to Sql class.
Snippet
ID (int, identifier)
Title (string)
SnippetType (int, FK on table SnippetTypes)
LanguageID (int, FK on table Languages)
Text (string)
Alright,
So I think the reason it is failing is because of the custom CSS that you are adding. ValidationMessageFor will put a hidden class when the validation is successful.
if you want to add custom colors or something like that with you CSS i would consider applying the style to the wrapping p tag or adding a wrapping div/span and adding it to that.
You could probably define your messages on the view using only #Html.ValidationMessageFor(snippet => snippet.SnippetTypeID, "ErrorMessage"); However a more proper way is to take your Model and create Data Annotations for it.
Take a look at this article http://www.asp.net/mvc/tutorials/older-versions/models-(data)/validation-with-the-data-annotation-validators-cs for more information about how to do model validation with Data Annotations.
Also I would consider passing in custom classes instead of your linq to sql class so that you can do custom validation based on the view. These custom classes are often refereed to as ViewModels.
On the edit page of my website I want users to be able to edit qty's and then have it change the model. This is why I am using 'editorFor'. The problem is that I still want to return the value of the model before it was edited to the controller post method.
For example, if a user edited a qty from 7 to 10, I would want the model to change to 10 but I would also want the view to return 7 to the controller. How can I do this?
Here is my editorFor code
<div class="form-group">
#Html.LabelFor(model => model.item_qty, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.item_qty, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.item_qty, "", new { #class = "text-danger" })
</div>
</div>
Here is my edit post method
[RestrictAccess(restriction = AccessRestrictions.ModifyWorkOrder)]
[HttpPost]
[ValidateAntiForgeryToken]
[Audit]
public ActionResult Edit([Bind(Include = "ID,JobOrderID,StartDate,CompleteDate,jobSection,ItemID,item_qty,actual_item_qty,ComponentID,comp_qty,actual_comp_qty,PartID,part_qty,actual_part_qty,Notes,subDetail")] JODetails jODetails)
{
if (ModelState.IsValid)
{
JobOrder jo = db.JobOrders.Find(jODetails.JobOrderID);
db.Entry(jODetails).State = EntityState.Modified;
JODetails currentData = db.JODetails.Find(jODetails.ID);
Component comp = db.Components.Find(jODetails.ComponentID);
Item i = db.Items.Find(jODetails.ItemID);
int newItemCount = jODetails.item_qty != null ? (int)jODetails.item_qty : 0;
int oldItemCount = 0;
int itemDiff = newItemCount - oldItemCount;
}
If I understand well enough, you don't need to return the value from the view. When the model is passed to the controller the value in the database has not been changed, you can read it again. Something like this:
// First. Grab the previous quantity...
// This approach won't work because of EF is already TRACKING the entity
// JODetails currentData = db.JODetails.Find(jODetails.ID);
// So, you have to access data like this...
var currentData = db.JODetails.AsNoTracking().FirstOrDefault(j => j.ID == jODetails.ID);
int previousQuantity = currentData?.item_qty;
//... do whatever with previousQuantity prop & new JODetails model. Don't forget to check if currentData is null
// Just NOW. Mutate the object via EF...
db.Entry(jODetails).State = EntityState.Modified;
// THEN. Commit changes...
db.SaveChanges();
It's not until you SaveChanges() that the record in the database it's really changed. Read some docs about how EF tracks, modifies & save objects.
This could be very helpful to understand this...
https://learn.microsoft.com/en-us/aspnet/mvc/overview/getting-started/introduction/examining-the-edit-methods-and-edit-view
Of course if you NEED to retrieve the Quantity data from the view (can't see why) there are some alternatives such as a ViewModel but I think this would do the trick. Yes, with this approach there's one more trip to the database, but it's minimal.