0

I have a database with folders where I store the whole path to a folder as a folder_name so sth. like: //MainFolder/subFolder/folderName. Im my application I have a Model called Folder, which represents the folders from db.

Model:

 public class Folder
 {   
    [Key]
    public string folder_name { get; set; }
    [NotMapped]
    public string folder_name_short
    {
       get
       {
           string shortname = folder_name.Substring(folder_name.LastIndexOf("/"), folder_name.Length - folder_name.LastIndexOf("/")); //System.NullReferenceException here
           return shortname;
       }
       set
       {
           string shortname = folder_name.Substring(folder_name.LastIndexOf("/"), folder_name.Length - folder_name.LastIndexOf("/"));
           this.folder_name = folder_name.Replace(shortname, value);
       }
    }
 }

folder_name_short isn't mapped because it is only a substring from the whole path, so I don't want to store it twice. Example want I mean:

Console.WriteLine(folder_name)          output://MainFolder/subFolder/folderName
Console.WriteLine(folder_name_short)    output:/folderName

In my View the user can rename the folder. So I would like to replace the old folder_name_short to the new one and store the new String in folder_name

View:

.
.
using (Html.BeginForm("Rename", "Folders", FormMethod.Post))
{
    @Html.EditorFor(model => model.folder_name_short)
    <input type="submit" value="rename folder" id="submit" class="btn btn-default" />
}
.
.

Problem: The Inputtextbox renders and shows the current Value of folder_name_short in it. When I change it and click the submit button, I get a System.NullReferenceException in the Model (as marked in the source code, please scroll to right). I don't understand what is wrong and what changes are needed.

Edit:

when the setter is commented out, the Exception disappear. So maybe the setter is causing the error?

Solution:

use the standard setter and getter for storing the folder_name_shortvalue, but implement a public get/set method to set the folder_name in the db and call this method in the controller. So:

[NotMapped]
public string folder_name_short { get; set; }
public string getfolder_name_short()
{
    string shortname = folder_name.Substring(folder_name.LastIndexOf("/"), folder_name.Length - folder_name.LastIndexOf("/"));
    return shortname;
}
public void setfolder_name_short(string newname)
{
    string shortname = folder_name.Substring(folder_name.LastIndexOf("/"), folder_name.Length - folder_name.LastIndexOf("/"));
    folder_name = folder_name.Replace(shortname, newname);
}
Paul S
  • 89
  • 12
  • Are you sure that Folder object is populated from database and also folder_name is not null after submit? – TSungur Mar 21 '16 at 12:28
  • Yes, the current Value of folder_name_short is visible in the imputbox. – Paul S Mar 21 '16 at 13:21
  • I mean when you submit the page, right before you come to the exception line (you could put a breakpoint on that line), look at the folder_name property is it other than null at this moment? – TSungur Mar 21 '16 at 14:03
  • Yes, the `folder_name` is null at this point. This is causing my problem, but I don'T understand why and what changes are needed. – Paul S Mar 21 '16 at 16:19

2 Answers2

1

If the value that is edited on the form is the short name folder_name_short then the model class could contain its string property:

public string folder_name_short { get; set; }

This property does not contain any logic. Any other code that contains some logic could be in the controller in an action method.

It seems you are using the same class for DB access and as a model class for the MVC view, which is the source of the problem.

Martin Staufcik
  • 8,295
  • 4
  • 44
  • 63
  • I'm relative new to asp.net, so excuse me for that question but what do you mean by "same class for DB access and as a model class for the MVC view"? If I don't implement this simple logic here, then I have to do it in every controller. Please also see my edit – Paul S Mar 21 '16 at 13:28
  • The class `Folder` is decorated with the `Key` attribute, from this I assumed that you are using this class in data access layer and also as a class for the view in the web application, is it the case? The model for a form and a model for an entity are usually different and then the one uinted class would contain mixed data, with different sets of decoration attributes (data mapping vs. form validation). It is cleaner to have a separate class for the view model. The logic that repeats can be put to a business class or to an utility (helper) class. – Martin Staufcik Mar 21 '16 at 15:06
  • Yes this is the case. I use this class in the View and for the datamapping. But it works for all other veiws and controllers. I mean I can get the `folder_name_short` in all other cases, but only in this view I try to set it and get an error on the **getter** not the setter. I don't understand why. Besides when I comment out the setter, the getter works without any exceptions – Paul S Mar 21 '16 at 16:55
0
[HttpPost]
[("Rename")]
public async Task<IHttpActionResult> ChangeFolderPath(Folder folder)
{
    //Put a breakpoint here and make sure the folder has a value
}

probably that the setter method overwrite the value of folder_name.

I would recommand this thread to help understand custom setters C# properties: how to use custom set property without private field?

EDIT

public class Folder
    {
        [Key]
        public string folder_name { get; set; }

        /*Model Logic shouldn't be in the Poco*/
        /*You may put that in your model or best thing would be to implement a repository pattern*/
        public string ShortName()
        {
            string shortname = folder_name.Substring(folder_name.LastIndexOf("/"), folder_name.Length - folder_name.LastIndexOf("/")); //System.NullReferenceException here
            return shortname;
        }
        public void SetUsingShortName(string value)
        {
            string shortname = folder_name.Substring(folder_name.LastIndexOf("/"), folder_name.Length - folder_name.LastIndexOf("/"));
            this.folder_name = folder_name.Replace(shortname, value);
        }
    }
Community
  • 1
  • 1
Alegrowin
  • 321
  • 1
  • 14
  • Do you want me to add this to my controller? I don't even come to the Rename Action in the controller, the exception in the Model comes before – Paul S Mar 21 '16 at 16:48
  • You should consider Replacing folder_name_short with a method instead of a property. I've updated my post – Alegrowin Mar 21 '16 at 18:06
  • When you need some logic to access your Poco (objects), best thing is to implement logic in a top level entity like the model. So you seperate the 'database entity' from the logic of setting dans getting the data and those methods could be reused somewhere else later. – Alegrowin Mar 21 '16 at 18:09