OK. Then you still want a zener diode to protect the transistor in event of rapid turnoff -- a zener+diode (back to back) so the flyback is clamped at something above VCC, rather than at VCC (as just a diode would do -- but that won't allow current to decay quickly!).
While a DAC is always better (and all of a single op-amp, better still ;-) ), you can do PWM by filtering.
You want the filter cutoff frequency no lower than the dominant time constant of the system, and preferably 3-10 times higher.
The PWM frequency has to be above the cutoff frequency for the filter to do anything. How much depends on the order of the filter, and how much attenuation you need, but for -40dB (a 1% ripple figure, probably not terrible?), a frequency ratio of 10, and a 4th or 5th order filter (two op-amps in Sallen-Key or MFB configuration, most likely), will do nicely.
In a control loop, you can often tolerate more ripple than usual (the system itself has some filtering value), so that maybe only -20dB, or even -10dB, is required. In this case, a pretty gentle filter can be used with a reasonable frequency ratio (F_PWM / F_c), or a modest filter can be used with an even more modest frequency ratio.
Probably, a ratio around 3, and a 3rd order filter (just because it's easy enough to implement, and needs only one op-amp), would do just fine.
Finally, the clock frequency must be at least F_PWM * 2^Nbits for Nbits worth of desired accuracy.
Once you have your filtered PWM, run that into a current source. Don't use a naked MOSFET. At least use a source degeneration resistor, so that the transconductance (current out / voltage in) becomes stabilized. Getting rid of the offset (Vgs(th) varies all over the place) probably isn't a big deal, as long as you burn a few volts in the source resistor. Or use a BJT -- no big loss adding 0.5% of base current, and it's that much easier to design for (Vbe is smaller, so its tempco matters less).
Note that, unless you've implemented linearizing controls (to account for the inverse-sqrt-of-cubes or whatever transfer function the solenoid effectively responds as -- in terms of force vs. distance at a given current), your loop gain and time constant will vary immensely with position. It might be pretty easy to stabilize the loop around a local point (exactly some position), but give it a bump and it starts oscillating, or becomes chaotic, or just drops it entirely. Or if you want it to pick up an object from your hand, same idea (a positional step response).
Tim