Acessing change of variable of an internal project in MVC [C#] - c#

I have an internal project (separated folder) in my MVC App. It contains classes of one of my projects.
Then I have one controller for this project and method that initializes it looks like this :
[HttpPost]
public ActionResult initiate() {
// System.Diagnostics.Debug.WriteLine("Initiated");
Network net = new Network(normalizeInput);
net.train();
// System.Diagnostics.Debug.WriteLine("average error :" + net.averageError);
double err = net.averageError;
ViewBag.err = err.ToString();
return View("initiate");
}
and its view :
#{
ViewBag.Title = "initiate";
}
<h3>Everything is prepared</h3>
<!--<button type="button" onclick="location.href='#Url.Action("initiate", "BackpropController")'"/> -->
#using (Html.BeginForm("initiate", "Backprop", FormMethod.Post)) {
#Html.AntiForgeryToken()
<input type="submit" value="Initiate" />
}
<br>
<br>
#{ string averageError = ViewBag.err;
if (averageError != null) {
<h4>#averageError</h4> }
else { <h4>no error</h4>}
}
The question is : How can I show in the view updated value by each iteration?
Because that variable is final one, but method train() contains loop where average error is like this :
averageError += Math.Abs(testingSet[j].desiredOutput - neuron.getOutput());
It interests me because I would like to make graph of error as it would be function of iteration.. simply said :
f(error,iteration)
The graph should be placed in the view I posted and should be updated every iteration situated in method train()
Thanks for the answers.

I am not sure if i understand your question correctly.
If you want to pass iteration on your view, you have to either:
pass the train() method return value (if any) to view
or
create View model you want to iterate from train() and pass it to view (preferable)
https://stackoverflow.com/a/18608533/5929494

You need to return the averageError values from your Network class train method to your controller. For example, you could do this with a property in the Network class such as...
class Network {
//your other code
public IEnumerable<double> averageErrors {get; set;}
public void train() {
averageErrors = new List<double>();
for (//your loop) {
averageError += Math.Abs(testingSet[j].desiredOutput - neuron.getOutput());
averageErrors.Add(averageError);
}
}
}
Then in your controller...
[HttpPost]
public ActionResult initiate() {
// System.Diagnostics.Debug.WriteLine("Initiated");
Network net = new Network(normalizeInput);
net.train();
// System.Diagnostics.Debug.WriteLine("average error :" + net.averageError);
double err = net.averageError;
// you now have a list of averageErrors in your controller to use as you please
List<double> allErrors = net.averageErrors;
ViewBag.err = err.ToString();
return View("initiate");
}
This gives you access to all the average errors after the train method has completed, so you can report this in the view however you like.
If train is a long-running method and you want to show a real-time update of average errors as the method is running, then things will get a bit more complicated. The general approach I would use would be to make the train method asynchronous, but not await it's execution before returning a view. The view will have placeholders, and use some form of client-side code to listen for updates e.g. SignalR. The train method would then periodically send updates to the client, and then finally send the completed data.

Related

HowTo: fix "No parameterless constructor defined for this object" in AngularJS/MVC app

I have a fairly complex CRM page that allows a user to schedule a class (like, where people actually attend and learn). The creation is done via a Modal that allows them to fill out some fields and press the Save button. That submission gathers the data entered into an object, and passes it to C#.
Or at least that's the goal. I've done it hundreds of times on other pages, with no problem, but in this instance I'm getting the "No parameterless constructor defined for this object" error. The thing is, it shouldn't BE parameterless - I'm passing params to it.
The AngularJS (1.7.5):
scAPI.DoTheThing({
classId : vm.item.Class.ClassId,
venueId : vm.item.Class.VenueId,
courseDate : vm.item.Class.CourseDate,
startTime : vm.item.Class.StartTime,
cost : vm.item.Class.Cost,
complianceComment: vm.item.Class.ComplianceComment,
isPrivate : hasValue(vm.item.Class.Private) ? vm.item.Class.Private : false,
instructors : vm.item.Instructors
})
.then(
function(result) {
var bob = 1;
}
)
.catch(function(errorOne) {
handleApiCallError(errorOne,
function() {
vm.readOnly = false;
vm.classSaving = false;
});
});
All of the parameters have values... "scAPI.DoTheThing" fires off this call:
DoTheThing: function (params, error) {
return $http
.post("/SchoolManagement/NewScheduledClass", params)
.then(handleNGV4Success)
.catch(function (e) {
handleNGV4Error(e, error);
});
}
which in turn should be hitting this C# method:
public ActionResult NewScheduledClass(int classId, int venueId, string courseDate, string startTime, decimal cost, string complianceComment, bool isPrivate,
IEnumerable<InstructorDataWithRoles> instructors)
{
var cDate = parseDate(courseDate);
var sTime = parseDate(startTime);
var newClass = _smap.NewScheduledClass(classId, venueId, cDate, sTime, cost, complianceComment, isPrivate, instructors);
var result = new
{
newClass
};
return HandleRequest(() => result);
}
Like I said, I've made this same kind of method call hundreds of times in this app, with no issues, but in this instance I'm having problems. The only thing I'm doing different in this C# controller.cs is that the Controller is a partial class. This particular controller handles 5 tabs worth of functionality in the UI, and I figured it would be best to put each tabs back end code into separate class files (ease of maintenance). This was the first-of-its-type in our solution, and all the other tabs are working fine, but this one is just screwed up for some reason.
All arguments that are passed to your controller method must have a parameterless constructor, as this is required by the default model binder.
Looking at your argument types, InstructorDataWithRoles must be the culprit.

How to pass collection data through form?

I'm writing a simple application in .net core mvc.
The problem is with loading related data by view. The 1st time I load the view it gets through wonderfully, I attach data to the view by entity framework include extensions function etc.
This code is on GET, when just displaying the item to be updated, filling fields with current values.
public IActionResult Edit(long id)
{
ServiceResult<LectureDTO> result = _lectureService.GetById(id, new LectureIncludeOptions(true));
LectureEditViewModel model = new LectureEditViewModel
{
Lecture = new LectureEditDTO(result.Entity)
};
if (!result.Success)
{
model.HandleResult(result, ModelState);
}
return View(model);
}
2nd time around when submitting a POST, IF the model I've submitted is not valid or the result of the update is not okay, I'd like to just attach errors to the model and send it to the view (by the HandleResult method).
public IActionResult Edit(LectureEditViewModel model)
{
if (!ModelState.IsValid)
{
ServiceResult<LectureDTO> getResult = _lectureService.GetById(model.Lecture.Id, new LectureIncludeOptions(true));
if (!getResult.Success)
{
model.HandleResult(getResult, ModelState);
}
model.Lecture = new LectureEditDTO(getResult.Entity);
return View(model);
}
ServiceResult<LectureDTO> result = _lectureService.Update(model.Lecture, User.FindFirstValue(ClaimTypes.NameIdentifier));
if (result.Success)
{
model = new LectureEditViewModel()
{
Lecture = new LectureEditDTO(result.Entity)
};
}
model.HandleResult(result, ModelState);
return View(model);
}
This is how I'm currently loading relationship data on bad editing. I think it's wasteful if I already had it in the model before, just displaying the edit form. Is there a way to pass this data by model?
I've tried this in my form to pass the collection, but everytime I debug this controller action, the value for it is empty.
<input asp-for="Lecture.Lecturers" value="#Model.Lecture.Lecturers" class="form-control" type="hidden" />
Am I going about this all wrong? Is what I've been doing okay? What could I improve?
Thanks for taking the time to help me with this.
As Chris Pratt pointed out in comment to my thread, you should not post any data to the server, you don't want the user to be able to change. Therefore my case for using collections in this way is invalid. To post collections to the server, write them out in input fields and post them.

output cache execution leads to object reference exception in session. How To Solve that?

Im Working in mvc C# project now. i just want to take some values from output cache. because it will reduce round robin in DB.
So i Used [OutputCache(Duration = 1800,VaryByParam = "none")]
when the action method is hitted for the first time, its getting the list values correctly,
Acually i assigned Duration for 30mins. So next request for that Action Method should not strike my DB, it has to give the cached Result.
BUt it lead to an exception, showing "Object reference not set to an instance of an object", which is from the Session
My Code is:
** This is Controller Action **
[HttpPost]
[OutputCache(Duration = 1800, Location = OutputCacheLocation.Server, VaryByParam = "none")]
public JsonResult GetStateList()
{
Result objResult = new Result();
VRecruitService.StateClient objState = new VRecruitService.StateClient();
using (CandidateModel objModel = new CandidateModel())
{
objResult.Data = objModel.GetStateList().Data;
}
return Json(objResult);
}
and ** This is model Class code, where im getting that exception **
public static Employee User
{
get
{
object objUser = HttpContext.Current.Session["userDetails"];
// In this above Session only im getting that Exception.
if (objUser is VRecruitService.Employee)
return (VRecruitService.Employee)objUser;
else
return null;
}
set
{
HttpContext.Current.Session["userDetails"] = value;
}
}
Please give me Solution. Thank you.
I believe that since you are caching the output, you need to decorate the controller class with
[SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)]
so that session state is available. Also it seems that an HttpGet verb may make more sense given that you are not POST'ing data to the action.

MVC UpdateModel is not updating some of the model properties

In my MVC 5 EF Database First project I have been using UpdateModel method in my controller action successfully, but after including some additional fields (previously unused by application) I find that the new fields simply refuse to get values from the UpdateModel method call. The only thing of any significance I can identify is that the fields share part of their name.
Consider this class as an example:
public class Record
{
public int ID {get;set;}
public string Details {get;set;}
public string DetailsFile {get;set;}
...
}
The property/field DetailsFile was previously unused, but now is an optional field on the web form. It is stored in a <input type="hidden" name="DetailsFile" id="DetailsFile /> and is successfully posted to the controller action with the correct value (or empty string).
Within the controller action I handle the update like this:
[HttpPost]
public async Task<ActionResult> Edit(Record_EditView model, FormCollection collection)
{
if (ModelState.IsValid)
{
try
{
var record = await db.Record.FindAsync(model.ID);
UpdateModel(record, collection);
db.Entry(record).State = EntityState.Modified;
await db.SaveChangesAsync();
}
catch(Exception ex)
{
throw ex;
}
}
// do more stuff here
...
}
Which has been working fine, but with the additional field all fields except the DetailsFile get updated from the FormCollection that is passed in. I have inspected both the model and the collection and they have the correct value, but the record never gets the values until I do a second post of the same data. Then the values get pushed in to the fields as expected.
I don't get any errors thrown and am at a bit of a loss as to what is going on. For the time being I have resorted to modifying my controller action to this:
[HttpPost]
public async Task<ActionResult> Edit(Record_EditView model, FormCollection collection)
{
if (ModelState.IsValid)
{
try
{
var record = await db.Record.FindAsync(model.ID);
UpdateModel(record, collection);
record.DetailsFile = collection["DetailsFile"]; // <-- Manually insert DetailsFile value
db.Entry(record).State = EntityState.Modified;
await db.SaveChangesAsync();
}
catch(Exception ex)
{
throw ex;
}
}
// do more stuff here
...
}
And this works OK, however I'm sure that I shouldn't have to do this, and hope that someone out there can explain what I am overlooking!
Finally found the problem, it is not likely to benefit many people but just in case here is the answer.
More Information
In my project I started using a jquery plugin for styling file input elements in a more bootstrap fashion, namely Jasny Bootstrap.
The plugin works great, however as part of it's internal workings it takes steps to maintain state of existing data and avoid post conflict by using hidden input and renaming the file input like this:
this.$hidden.val('')
this.$hidden.attr('name', '')
this.$input.attr('name', this.name)
The Problem
Which ends up with element(s) that have an attribute name="" and that caused the page to post the element and the FormCollection to include an empty/"" item(s).
Despite the fact that no errors were thrown, nonetheless it seems to break the call to
UpdateModel(record,collection)
The Solution
To fix this and avoid posting the selected file (my project doesn't actually want the file to be posted, just the file path) I just intercept the form submit to remove the unwanted form elements prior to posting:
$('form').submit(function (e) {
e.preventDefault();
// get rid of any input elements that have name="" or file elemnts so will not mess with the posted form collection
$('input[name=""],input[type="file"]').remove();
this.submit();
})

Differentiate Create from Update in Content Part Driver in Orchard CMS

I want to serve different views which use different ViewModel objects depending on Actions. This can be achieved in a conventional ASP.NET MVC paradigm.
[HttpGet]
public ActionResult Create() {
return View(new CreateViewModel()); //this serves Create.cshtml View
}
[HttpGet, ActionName("Create")]
public ActionResult CreatePOST(CreateViewModel viewModel) {
if (!ModelState.IsValid) {
return View(viewModel); //if error, re-serve Create.cshtml View
}
// Create new model into database
return RedirectToAction("Index");
}
[HttpGet]
public ActionResult Edit(int Id) {
var model = RetriveModel(Id);
var viewModel = new EditViewModel { Id = model.Id, Name = model.Name };
return View(viewModel); //this serves Edit.cshtml
}
[HttpPost, ActionName("Edit")]
public ActionResult EditPOST(EditViewModel viewModel) {
if (!ModelState.IsValid) {
return View(viewModel); //if error, re-serve Edit.cshtml View
}
// Update model in database
return RedirectToAction("Index");
}
How do I do the same to Orchard Content Part? It seems that the overridable Editor method in a ContentPartDriver fused both Create and Update actions together. How do I tell if the method is creating or updating? Something like
// GET
protected override DriverResult Editor(CustomContentPart part, dynamic shapeHelper) {
if (IsNewRecord) {
return ContentShape("Parts_CustomContentPart_Create" () =>
shapeHelper.EditorTemplate(TemplateName: "Parts/CreateTemplate", Model: new CreateViewModel(), Prefix: Prefix)
);
} else {
return ContentShape("Parts_CustomContentPart_Edit" () =>
shapeHelper.EditorTemplate(TemplateName: "Parts/EditTemplate", Model: BuildEditViewModel(part), Prefix: Prefix)
);
}
}
// POST
protected override DriverResult Editor(CustomContentPart part, IUpdateModel updater, dynamic shapeHelper) {
object viewModel;
if (IsNewRecord) {
viewModel = new CreateViewModel();
} else {
viewModel = new EditViewModel();
}
update.TryUpdateModel(viewModel, Prefix, null, null);
return Editor(part, shapeHelper);
}
I'm a beginner in Orchard still learning the ropes on how Orchard does things. Pardon me if my questions are too trivial.
Check for a content item id, if it is null, or possibly 0, I forget, then you are in the process of creating a content item. If it does have a value then you are editing. You can also use this in your view, can be quite handy.
If you need custom functionality to be called on creation/updating then you could consider using handler methods?
So in your parts handler add something like
OnCreated<MyPart>((ctx, part) => CreateItems(part));
Where CreateItems is a method with your part as a parameter. There are a bunch of content item events you can hook into, there is a neat list in the docs: http://docs.orchardproject.net/Documentation/Understanding-content-handlers
As always, check the source code for good examples of their usage.
EDIT
Apparently checking for null id doesn't work, I checked in some of my modules were I used it and have used the following check:
Model.ContentItem.VersionRecord == null || !Model.ContentItem.VersionRecord.Published
Although this question has been asked and answered, just thought of posting my findings so I can find it later.
ContentItem.Id is indeed 0 when the content item isn't created yet. For example, when you're about to create a new Page, ContentItem.Id == 0. Now just click on the Save button without filling up the form and validation will fail since the required field Title wasn't provided and we're getting back the same view with an error. Since validation failed, technically we don't consider the content item to be created yet. However, at this point Orchard already treating it as an existing content item. Orchard even went as far as obtaining and increasing the Identity counter of the Content Item Record table (Orchard_Framework_ContentItemRecord) from the database and assigning it as an Id to the content item.
Orchard even wired up all the Version Records, making it pretty much a full-fledged content item. All these for a content item that failed validation during creation and facing possibility of being discarded altogether. The only thing Orchard hasn't done is inserting it into the database (it's only residing in memory at this point). Therefore there's really no other ways to tell if a content item is an existing one or one that was about to be created other than checking it against the database and see if the content item was really there.
var contentItemRepository = _workContext.Resolve<IRepository<ContentItemRecord>>();
var contentItemRecord = contentItemRepository.Get(Model.ContentItem.Id);
if (contentItemRecord == null) {
isNew = true;
}
or we could also use the IContentManager to do the same thing
var contentManager = Model.ContentItem.ContentManager;
var contentItem = contentManager.Get(Model.ContentItem.Id, VersionOptions.AllVersions);
if (contentItem == null) {
isNew = true;
}
Edit:
Apparently I spoke too soon. When I said above that Orchard hasn't inserted the content item into the database yet and it still resides in memory, it actually already in the database, in a yet to be committed Transaction. In the case above where validation fails, the transaction will be rolled back at the end. The correctness of the above code depends on when it was executed. If it was executed before the transaction was cancelled and rolled back, the content item is still in the database and won't yield an accurate result. If it was executed after transaction rollback (eg. in a View), then it'll behave as expected.
How Orchard handles content item creation can be seen in Orchard.Core.Contents.Controllers.AdminController.CreatePOST(string, string, Action<ContentItem>):
_contentManager.Create(contentItem, VersionOptions.Draft);
var model = _contentManager.UpdateEditor(contentItem, this);
if (!ModelState.IsValid) {
_transactionManager.Cancel();
return View(model);
}
The content item was being created first before it was being fed into IContentManager.UpdateEditor() to validate.
Update:
Filed a bug at
https://github.com/OrchardCMS/Orchard/issues/6534

Categories

Resources